leetcode brush record day002:189 and 217

Posted by dunnsearch on Fri, 17 Sep 2021 04:04:11 +0200

189. Medium difficulty: the content refers to the official answer

Think of the array as a ring connected end to end. Moving right is equivalent to rotating the ring
Requirements: 1. Use the in-situ algorithm with spatial complexity O(1) to solve this problem; 2. There are at least three different ways to solve this problem

Problem solving ideas:
1. O(1) is the lowest spatio-temporal complexity, that is, the time / space consumption is independent of the size of the input data. No matter how many times the input data is increased, the time / space consumption remains the same.
For example, if int is a variable, no matter how large the value is, the time and space consumption will remain the same. The cycle is not painful. The larger the value, the more cycles and time-consuming.
2. Since it is required to solve in situ, we should create a formula to solve the position transformation problem.
The formula for obtaining the next position of the current element by rotation should meet the requirement that the element can reach the first position when it is in the n position. That is, take the remainder.

Method 1: use additional array: time complexity: O(n), where n is the length of the array. Space complexity: O(n).

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr = new int[n];
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}

1. System. Arraycopy (newArr, 0, num, 0, n); expressed as: copy the value from bit 0 to bit n in the newArr source array to the num target array, and place it at bit 0 of the target array.
2. Remainder: (i+k)%n: assuming that the current array length is n and the current element is item i, move item K to the right. If i+k cannot reach position n, even (i+k)%n is equal to i+k itself.
If it exceeds n, we can think of adding a part of k to i to be equal to N, and then the actual position after rotation is the rest of k except that part.
How to find the remaining part: i+k can be regarded as a n (a is a positive integer) and the remaining part less than the final actual position of N. so take the remainder directly.

Method 2: Ring replacement: time complexity: O(n), where n is the length of the array. Each element will only be traversed once, and space complexity: O(1). We only need to store several variables in the constant space.

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k = k % n; //If k is less than N, it is still k itself. If it is greater than the direct remainder, remove the integer multiple of n (i+k remainder is not necessary, k itself also belongs to location information, and can be taken separately)
        int count = gcd(k, n); //The principle of this method is shown in the following derivation process. count is the total number of passes we need
        for (int start = 0; start < count; ++start) { //The traversal starts from subscript 0, ends at 0, ends at 1, and ends at 2. The total traversal reaches count-1
            int current = start;
            int prev = nums[start]; //Previous (item to be moved to the right)
            do {
                int next = (current + k) % n; //The location to move the current item to
                int temp = nums[next]; //Save the item value of the moving position, otherwise the data will be lost
                nums[next] = prev; //Puts the current item in a new location
                prev = temp; //The current item is the item that has lost its original position and is about to be placed in its moved position
                current = next; //current: the original location of the element to be processed (next has been occupied by other elements)
            } while (start != current); //If the current pending position is the same as the starting position of this round of traversal, it means that the next round of traversal can be carried out (the principle is below)
        }
    }
    public int gcd(int x, int y) {
        return y > 0 ? gcd(y, x % y) : x;
    }
}

The reason for using additional arrays in method 1 is that if we directly put each number to its last position, the elements placed will be overwritten and lost. Therefore, from another point of view, we can save the replaced elements in the variable temp, thus avoiding the overhead of additional arrays.
We start from position 0 and initially make temp = num [0]. According to the rules, the element of position 0 will be placed at the position of (0+k)mod n and make x=(0+k)\bmod nx=(0+k)mod n. at this time, exchange temp and num [x] and complete the update of position x (temp retains the value of the current replaced position element / the value of the next element to be processed). Then, we investigate position X and exchange temp and num [(x + k) Mod n], so as to complete the update of the next position. Continue the above process until it returns to the initial position 0 (one round of traversal ends, and this round of traversal processes more than 1 element)

It is easy to find that when we return to the initial position 0, some numbers may not have been traversed. At this time, we should start the repeated process from the next number, but how can the traversal end? We might as well consider such a question first: how many elements have we traversed in the process of continuously traversing from 0 and finally returning to the starting point 0?

Since we finally return to the starting point, the process happens to take an integer number of cycles, which may be set as cycle a; let the process traverse a total of B elements. Therefore, we have a * n=b * k, that is, an must be the common multiple of N and K. also, because we end when we return to the starting point for the first time, a should be as small as possible, so an is the least common multiple lcm(n,k) of N and K Therefore, B is lcm(n,k)/k.

This shows that a single traversal will access klcm(n,k)/k elements. In order to access all elements, we need to traverse the number of times
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-Ni0cYdQ1-1631785496384)(189. Rotating array. assets/image-20210916160247657.png)]

gcd refers to the maximum common divisor. A specific example is shown in the figure below (Num = [1, 2, 3, 4, 5, 6], k = 2)

Method 3: array flipping: time complexity: O*(*n), where n is the length of the array. Each element is flipped twice, a total of n elements, so the total time complexity is O(2n)=O(n), and the space complexity is O(1)

class Solution {
    public void rotate(int[] nums, int k) { //Main method
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }

    public void reverse(int[] nums, int start, int end) { //Flip
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start += 1;
            end -= 1;
        }
    }
}

Let's take n=7n=7, k=3k=3 as an example to show as follows:

Operation results
Original array 1 2 3 4 5 6 7
Flip all elements 7 6 5 4 3 2 1
Flip the elements of the [0,kmodn − 1] interval 5 6 7 4 3 2 1
Flip the elements of the [kmodn,n − 1] interval 5 6 7 1 2 3 4

Turning over once will make the order disordered, but turning over twice is equal to the original order, so we turn over the whole first, and then set the scope we need locally to turn over.

217. The difficulty is simple: the difficulty of this question: there is a time limit, so try not to use two-layer for loop

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] == nums[i + 1]) {
                return true;
            }
        }
        return false;
    }
}

Principle: after sorting numbers from small to large, the repeated elements of the array must appear in adjacent positions. Therefore, we can scan the sorted array and judge whether the adjacent two elements are equal each time. If they are equal, it indicates that there are repeated elements.

Topics: Java Algorithm data structure leetcode