Sword finger Offer (2nd Edition)

Sword finger Offer 03. Duplicate number in array

Topic introduction

Find duplicate numbers in the array.

All numbers in an array num of length n are in the range of 0 ~ n-1. Some numbers in the array are repeated, but I don't know how many numbers are repeated, or how many times each number is repeated. Please find any duplicate number in the array.

Example 1:

Input:
[2, 3, 1, 0, 2, 5, 3]
Output: 2 or 3 

Limitations:

  • 2 <= n <= 100000

Source: LeetCode
Link: https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

We can take advantage of the feature that set set elements cannot be repeated, cycle through the array elements and add them to the set set in turn. If the addition fails, it means that the number is repeated.

class Solution {
    public int findRepeatNumber(int[] nums) {
        HashSet<Integer> hashSet = new HashSet<>();
        for (int num : nums) {
            if (!hashSet.add(num)) {
                return num;
            }
        }
        return -1;
    }
}

Sword finger Offer 06. Print linked list from end to end

Topic introduction

Enter the head node of a linked list, and return the value of each node from tail to head (returned by array).

Example 1:

Input: head = [1,3,2]
Output:[2,3,1]

Limitations:

  • 0 < = linked list length < = 10000

Source: LeetCode
Link: https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

The stack is characterized by last in first out, that is, the last element pushed into the stack pops up first. Considering this characteristic of stack, stack is used to invert the order of linked list elements. Start from the head node of the linked list, press each node into the stack in turn, then pop up the elements in the stack in turn and store them in the array.

class Solution {
    public int[] reversePrint(ListNode head) {
        Stack<ListNode> stack = new Stack<>();
        while (head != null) {
            stack.push(head);
            head = head.next;
        }
        int size = stack.size();
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = stack.pop().val;
        }
        return arr;
    }
}

Sword finger Offer 09. Queue with two stacks

Topic introduction

Implement a queue with two stacks. The declaration of the queue is as follows. Please implement its two functions appendTail and deleteHead to insert integers at the end of the queue and delete integers at the head of the queue respectively. (if there are no elements in the queue, the deleteHead operation returns - 1)

Example 1:

Input:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
Output:[null,null,3,-1]

Example 2:

Input:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
Output:[null,-1,null,null,5,2]

Tips:

  • 1 <= values <= 10000
  • At most 10000 calls will be made to appendTail and deleteHead

Source: LeetCode
Link: https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

The characteristic of queue is FIFO (first in first out), while the characteristic of stack is FILO (first in first out).

After knowing the characteristics of the two, we need to use two stacks to simulate the characteristics of the queue. One stack is the incoming stack and the other is the outgoing stack.

When there is content in the outgoing stack, the top of the outgoing stack is the first outgoing element.

If there are no elements in the out of queue stack and our demand is out of queue, we need to import the contents of the in queue stack out of the queue stack in reverse order, and then pop up the top of the stack.

Note: according to the characteristics of the stack, we can only use push and pop operations.

class CQueue {
    private Stack<Integer> inStack;
    private Stack<Integer> outStack;

    public CQueue() {
        inStack = new Stack<>();
        outStack = new Stack<>();
    }

    public void appendTail(int value) {
        inStack.push(value);
    }

    public int deleteHead() {
        if (outStack.isEmpty()) {
            while (!inStack.isEmpty()) {
                outStack.push(inStack.pop());
            }
        }
        if (outStack.isEmpty()) {
            return -1;
        } else {
            return outStack.pop();
        }
    }
}

Sword finger Offer 15. Number of 1 in binary

Topic introduction

Please implement a function to input an integer (in the form of binary string) and output the number of 1 in the binary representation of the number. For example, representing 9 as binary is 1001, and 2 bits are 1. Therefore, if you enter 9, the function outputs 2.

Example 1:

Input: 0000000000000000000000001011
 Output: 3
 Explanation: there are three digits in the binary string 0000000000000000000000000000001011 '1'. 

Example 2:

Input: 000000000000000000000000000000000000000000000
 Output: 1
 Explanation: in the binary string 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '1'. 

Example 3:

Input: 11111111111111111111111111111111101
 Output: 31
 Explanation: there are 31 bits in the input binary string 11111111111111111111111111111101 '1'. 

Tips:

  • The input must be a binary string of length 32.

Source: LeetCode
Link: https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

  • According to the definition of and operation, if the binary number n is set, there are:
    • If n & 1 = 0, the rightmost bit of N binary is 0;
    • If n & 1 = 1, the rightmost bit of N binary is 1.
  • According to the above characteristics, consider the following cycle judgment:
    • Judge whether the rightmost bit of n is 1 and count according to the result.
    • Shift n one bit to the right (this question requires that the number n be regarded as an unsigned number, so the unsigned right shift operation is used).
public class Solution {
    public int hammingWeight(int n) {
        int count = 0;
        while (n != 0) {
            count += n & 1;
            n >>>= 1;
        }
        return count;
    }
}

Sword finger Offer 47. Maximum value of gift

Topic introduction

There is a gift in each grid of an m*n chessboard, and each gift has a certain value (value greater than 0). You can start from the upper left corner of the chessboard to take the gifts in the grid, and move one grid to the right or down at a time until you reach the lower right corner of the chessboard. Given the value of a chessboard and the gifts on it, please calculate the maximum value of gifts you can get?

Example 1:

input: 
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
output: 12
 explain: Path 1→3→5→2→1 You can get the most valuable gift

Tips:

  • 0 < grid.length <= 200
  • 0 < grid[0].length <= 200

Similar topics:

Source: LeetCode
Link: https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

Start from the upper left corner of the chessboard, take the gifts in the grid, and move one grid to the right or down at a time until you reach the lower right corner of the chessboard.

According to the title description, it is easy to get a cell that can only be reached from the upper cell or the left cell.

Let f(i,j) be the maximum cumulative value of the gift from the upper left corner of the chessboard to cell (I, J). It is easy to get the following recursive relationship: f(i,j) is equal to the larger value of f(i,j-1) and f(i-1,j) plus the current cell gift value grid(i,j).

Therefore, dynamic programming can be used to solve this problem, and the above formula is the transfer equation.

Since dp[i][j] is only related to dp [I-1] [J], dp[i][j-1], grid [i] [J], the original matrix grid can be used as the dp matrix, that is, it can be modified directly on the grid. This method can save the additional space used by dp matrix, so the space complexity is reduced from O(MN) to O(1).

class Solution {
    public int maxValue(int[][] grid) {
        // Judgment of critical value
        int rows = grid.length;
        int cols = grid[0].length;
        if (grid == null || rows == 0 || cols == 0) return 0;
        // Initialize the first column
        for (int i = 1; i < rows; i++) {
            grid[i][0] = grid[i - 1][0] + grid[i][0];
        }
        // Initialize the first line
        for (int i = 1; i < cols; i++) {
            grid[0][i] = grid[0][i - 1] + grid[0][i];
        }
        // Dynamic programming core
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                grid[i][j] = Math.max(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
            }
        }
        // Returns the last element
        return grid[rows - 1][cols - 1];
    }
}

Sword finger Offer 49. Ugly number

Topic introduction

We call numbers containing only qualitative factors 2, 3 and 5 ugly numbers. Find the nth Ugly Number in the order from small to large.

Example:

input: n = 10
 output: 12
 explain: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 It's the top 10 ugly numbers.

explain:

  • 1 is the ugly number.
  • n not more than 1690.

Same title:

Source: LeetCode
Link: https://leetcode-cn.com/problems/chou-shu-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

class Solution {
    public int nthUglyNumber(int n) {
        int[] dp = new int[n];
        dp[0] = 1;
        int t2 = 0, t3 = 0, t5 = 0;
        for (int i = 1; i < n; i++) {
            int next2 = dp[t2] * 2, next3 = dp[t3] * 3, next5 = dp[t5] * 5;
            dp[i] = Math.min(Math.min(next2, next3), next5);
            if (next2 == dp[i]) t2++;
            if (next3 == dp[i]) t3++;
            if (next5 == dp[i]) t5++;
        }
        return dp[n - 1];
    }
}

Sword finger Offer 59 - I. maximum value of sliding window

Topic introduction

Given an array num and the size k of the sliding window, please find the maximum value in all sliding windows.

Example:

input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
 output: [3,3,5,5,6,7] 
explain: 

  Position of sliding window                Maximum

---------------               -----

[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

Tips:

  • You can assume that k is always valid. When the input array is not empty, 1 ≤ k ≤ the size of the input array.

Same title:

Source: LeetCode
Link: https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

Sliding window is mentioned in the title. Let's take an example to see what is sliding window?

In the example, we start from the first element in the array. Since the size of the window is 3, when we traverse to the third element, the window is formed.

After that, when you continue to traverse the elements, in order to keep the window size of 3, the left element needs to be removed from the window. This causes the window to move to the right until the end of the last element is observed, which is called a sliding window.

In the process of forming and moving the sliding window, we notice that the elements enter from the right side of the window, and then because the window size is fixed, the redundant elements are removed from the left side of the window. One end enters and the other end removes. Isn't that the nature of the queue? Therefore, the problem can be solved with the help of queue.

The title requirement is to return the maximum value in each window. So how to solve this problem?

We describe it with the array {5, 3, 4, 1} and the window size k=3. Here, we specify that the right boundary of the window is right, the left boundary is left, and its value is the element subscript.

Then, start traversing num = {5, 3, 4, 1}. When right points to the first element 5, the queue is empty and the first element 5 is queued.

Continue to look at the second element 3. At this time, 3 is smaller than element 5 at the end of the queue, so element 3 is queued to see whether it is the maximum value of the next window. At this time, the elements in the queue decrease from the head of the queue to the end of the queue.

Next, we investigate the third element 4 in {5, 3, 4, 1}. At this time, 4 is larger than the tail element 3, which indicates that element 3 cannot be the largest element in the window "5, 3, 4", so it needs to be removed from the queue. But the team leader has element 5, so it can't be removed from the team leader. What should I do? We can remove it from the end of the team.

This kind of queue in which both elements can join the queue and elements can leave the queue at one end is called two-way queue.

After the tail element 3 leaves the team, since the new tail element 5 is larger than the current investigation element 4, element 4 joins the team to see whether it is the maximum value of the next window.

When element 4 enters the queue, we find that at this time, the elements in the queue are still decreasing from the head to the tail.

We call the decreasing or increasing queue from the head of the team to the end of the team monotonic queue.

Next, look at the fourth element 1. At this time, element 1 is smaller than the end of the queue element 4, so element 1 joins the queue.

However, at this time, there are four elements in the window, and we specify that the window size is 3. Therefore, we need to reduce the left boundary of the window. After narrowing the left edge of the window, it means that element 5 is no longer in the window. Therefore, the first element 5 needs to be out of the team. That is, when the subscript of the queue head element in the original array is less than the left boundary of the window, the queue head element needs to be removed.

So far, the solution idea of the problem is clear, as follows:

  • Traverse the elements in the given array. If the queue is not empty and the current inspected element is greater than or equal to the tail element, the tail element will be removed. Until, the queue is empty or the current investigation element is smaller than the new tail element;
  • When the subscript of the team head element is less than the left boundary of the sliding window, it indicates that the team head element is no longer in the sliding window, so it is removed from the team head.
  • Since the array subscript starts from 0, when the window right boundary right+1 is greater than or equal to the window size k, it means that the window is formed. At this point, the queue head element is the maximum value in the window.

It should be noted that in the above demonstration, the queue stores element values. In the specific code implementation, in order to facilitate calculation, the subscript of the element is stored in the queue.

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0) return new int[0];
        // Define a double ended queue to store the subscript of the maximum value. Note: it is not an array element
        Deque<Integer> deque = new LinkedList<>();
        // How to determine the number of windows? nums.length - (k - 1) = nums.length - k + 1
        int[] ans = new int[nums.length - k + 1];
        // Traverse the elements in the array. Right represents the right boundary of the sliding window
        for (int right = 0; right < nums.length; right++) {
            // If the queue is not empty and the current review element is greater than or equal to the tail element, the tail element is removed.
            // Until the queue is empty or the current review element is smaller than the new tail element
            while (!deque.isEmpty() && nums[right] >= nums[deque.getLast()]) {
                deque.removeLast();
            }
            // Storage element subscript
            deque.addLast(right);
            // Left boundary of calculation window
            int left = right - k + 1;
            // When the subscript of the team head element is less than the left boundary of the sliding window
            // Indicates that the team leader element is no longer in the sliding window, so it is removed from the team leader
            if (deque.getFirst() < left) {
                deque.removeFirst();
            }
            // Since the array subscript starts from 0, when the window right boundary right+1 is greater than or equal to the window size k
            // It means that the window is formed. At this point, the queue head element is the maximum value in the window
            if (right + 1 >= k) {
                ans[left] = nums[deque.peekFirst()];
            }
        }
        return ans;
    }
}

Sword finger Offer 59 - II. Maximum value of queue

Topic introduction

Please define a queue and implement the function max_value gets the maximum value in the queue and requires the function max_value,push_back and pop_ The average sharing time complexity of front is O(1). If the queue is empty, pop_front and max_value needs to return - 1.

Example 1:

input: 
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
output: [null,null,null,2,1,2]

Example 2:

input: 
["MaxQueue","pop_front","max_value"]
[[],[],[]]
output: [null,-1,-1]

Limitations:

  • 1 <= push_ back,pop_ front,max_ Total operands of value < = 10000
  • 1 <= value <= 105

Source: LeetCode
Link: https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

Directly implement a common queue and traverse the calculation when querying the maximum value.

class MaxQueue {
    int[] queue = new int[10000];
    int begin = 0, end = 0;

    public MaxQueue() {}

    public int max_value() {
        int ans = -1;
        for (int i = begin; i != end; i++) {
            ans = Math.max(ans, queue[i]);
        }
        return ans;
    }

    public void push_back(int value) {
        queue[end++] = value;
    }

    public int pop_front() {
        if (begin == end) {
            return -1;
        }
        return queue[begin++];
    }
}

Sword finger Offer 64. Find 1 + 2 +... + n

Topic introduction

For 1+2+...+n, it is required that keywords such as multiplication and division, for, while, if, else, switch, case and conditional judgment statements (A?B:C) cannot be used.

Example 1:

input: n = 3
 output: 6

Example 2:

input: n = 9
 output: 45

Limitations:

  • 1 <= n <= 10000

Source: LeetCode
Link: https://leetcode-cn.com/problems/qiu-12n-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

Topic realization

This problem uses Gauss summation formula to replace multiplication and division with bit operation.

Text expression: and = (first item + last item) x number of items / 2

Mathematical expression: 1 + 2 +... + n = (n+1) n / 2

class Solution {
    public int sumNums(int n) {
        return (1 + n) * n >> 1;
    }
}

Tags: Algorithm

Posted on Tue, 28 Sep 2021 14:04:39 -0400 by mrwowza