977. Square of ordered array
[LeetCode]
simple single \color{#00AF9B} {simple} simple
Give you an integer array nums sorted in non decreasing order, and return a new array composed of the square of each number. It is also required to sort in non decreasing order.
Example 1:
Input: nums = [4,1,0,3,10] Output:[0,1,9,16,100] Explanation: after squaring, the array becomes [16,1,0,9,100] After sorting, the array becomes [0,1,9,16,100]
Example 2:
Input: nums = [7,3,2,3,11] Output:[4,9,9,49,121]
Tips:
 1 <= nums.length <= 104
 104 <= nums[i] <= 104
 nums is sorted in non decreasing order
Advanced:
Please design an algorithm with time complexity O(n) to solve this problem
Method 1: direct sort
The idea of this method is very simple. After each item in the array is squared, the whole array is sorted.
#include <vector> #include <algorithm> using namespace std; class Solution { public: vector<int> sortedSquares(vector<int> &nums) { vector<int> ans; ans.reserve(nums.size()); for (int num : nums) { ans.emplace_back(num * num); } sort(ans.begin(), ans.end()); return ans; } };
Complexity analysis
Time complexity: O(n logn)
Spatial complexity: O(logn). The array of answers is not included. We need O(logn) stack space to sort.
Reference results
Accepted 137/137 cases passed (32 ms) Your runtime beats 46.63 % of cpp submissions Your memory usage beats 56.4 % of cpp submissions (25.3 MB)
Method 2: double pointer
We can set two pointers left and right to point to the beginning and end of the array respectively. In each loop, compare the sizes of num [left] ^ 2 and num [right] ^ 2, put the largest value at the end of the answer array in reverse order, and then change the corresponding pointer.
Process demonstration:
#include <vector> using namespace std; class Solution { public: vector<int> sortedSquares(vector<int> &nums) { int n = nums.size(); vector<int> ans(n); for (int left = 0, right = n  1, k = n  1; left <= right; k) { int a = nums[left] * nums[left], b = nums[right] * nums[right]; if (a > b) { ans[k] = a; left++; } else { ans[k] = b; right; } } return ans; } };
Complexity analysis
Time complexity: O(n)
Space complexity: O(1). The array of answers is not included. We only need a constant space to store several variables.
Reference results
Accepted 137/137 cases passed (24 ms) Your runtime beats 85.42 % of cpp submissions Your memory usage beats 78.88 % of cpp submissions (25.2 MB)
189. Rotation array
in etc. \color{#FFB800} {medium} secondary
Give you an array, rotate the elements in the array K positions to the right, where k is a non negative number.
Example 1:
input: nums = [1,2,3,4,5,6,7], k = 3 output: [5,6,7,1,2,3,4] explain: Rotate 1 step to the right: [7,1,2,3,4,5,6] Rotate right for 2 steps: [6,7,1,2,3,4,5] Rotate right for 3 steps: [5,6,7,1,2,3,4]
Example 2:
Input: nums = [1,100,3,99], k = 2 Output:[3,99,1,100] explain: Rotate 1 step to the right: [99,1,100,3] Rotate right for 2 steps: [3,99,1,100]
Tips:
 1 <= nums.length <= 105
 231 <= nums[i] <= 231  1
 0 <= k <= 105
Advanced:
 Think of as many solutions as possible. There are at least three different ways to solve this problem.
 Can you use the insitu algorithm with spatial complexity O(1) to solve this problem?
be careful
 The title requires modification on the original array, rather than returning a new array.
 Move the whole array nums by k bits to the right
 The value of k may exceed the length of the array. That is, move the whole array k/n times, return to the original position, and then move k%n times to get a new array. Therefore, when calculating the subscript, we must not forget that the final result should take the remainder of n.
Method 1: use additional arrays
This may be the simplest idea of the topic. We can define an array dummy with the same length as the original array nums, and put the results into the new array dummy in order. Finally, replace all items in nums with data in dummy.
According to the meaning of the title, in the original array with length n, the item i is moved k bits to the right and stored in the new array, then the subscript of item i in the new array can be obtained from the following mapping relationship:
i
→
(
i
+
k
)
%
n
i \rightarrow (i+k)\%n
i→(i+k)%n
Namely:
d
u
m
m
y
[
(
i
+
k
)
%
n
]
=
n
u
m
s
[
i
]
dummy[(i + k) \% n] = nums[i]
dummy[(i+k)%n]=nums[i]
#include <vector> using namespace std; typedef unsigned int ui; class Solution { public: void rotate(vector<int> &nums, int k) { int n = nums.size(); vector<int> dummy(n); for (int i = 0; i < n; i++) { dummy[(i + k) % n] = nums[i]; } nums.assign(dummy.begin(), dummy.end()); } };
Complexity analysis
Time complexity: O(n)
Space complexity: O(n)
Reference results
Accepted 38/38 cases passed (28 ms) Your runtime beats 49.29 % of cpp submissions Your memory usage beats 27.54 % of cpp submissions (24.9 MB)
Method 2: three flips
Let's take the array [1,2,3,4,5,6,7] and k=3 as examples to observe the original array and the results:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
]
[
5
,
6
,
7
,
1
,
2
,
3
,
4
]
[1,2,3,4,\color{red}{5} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{7} \color{#000000}{}] \\ [\color{red}{5} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{7} \color{#000000}{},1,2,3,4]
[1,2,3,4,5,6,7][5,6,7,1,2,3,4]
Let's flip the K items on the left and the nk items on the right in the results respectively:
[
7
,
6
,
5
,
4
,
3
,
2
,
1
]
[\color{red}{7} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{5} \color{#000000}{},4,3,2,1]
[7,6,5,4,3,2,1]
You can find that it is the global flip of the original array. In other words, the process from the original array to the result array is as follows:
 Global flip
 Left kterm flip
 Right nk term flip
Namely:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
]
↓
1
[
7
,
6
,
5
,
4
,
3
,
2
,
1
]
↓
2
[
5
,
6
,
7
,
4
,
3
,
2
,
1
]
↓
3
[
5
,
6
,
7
,
1
,
2
,
3
,
4
]
[1,2,3,4,\color{red}{5} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{7} \color{#000000}{}] \\ {\downarrow}_{1} \\ [\color{red}{7} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{5} \color{#000000}{},4,3,2,1] \\ {\downarrow}_{2} \\ [\color{red}{5} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{7} \color{#000000}{},4,3,2,1] \\ {\downarrow}_{3} \\ [\color{red}{5} \color{#000000}{},\color{red}{6} \color{#000000}{},\color{red}{7} \color{#000000}{},1,2,3,4]
[1,2,3,4,5,6,7]↓1[7,6,5,4,3,2,1]↓2[5,6,7,4,3,2,1]↓3[5,6,7,1,2,3,4]
These three steps are the same process, that is, flip the array from a start item to an end item. Therefore, these three steps can be regarded as three function calls. We can define this function as reverse(). The flipping process can be completed by double pointers.
We can set the two pointers left and right to point to the start item and the end item respectively, exchange the values pointed to by the two pointers each time, and then advance one unit to the middle until they point to the same element (an element does not need to be exchanged with itself) or left runs to the right of right, and the loop ends. Thus, the effective condition of the cycle can be determined as left < right.
#include <vector> using namespace std; class Solution { public: void rotate(vector<int> &nums, int k) { int n = nums.size(); k %= n; reverse(nums, 0, n  1); reverse(nums, 0, k  1); reverse(nums, k, n  1); } void reverse(vector<int> &nums, int left, int right) { while (left < right) { swap(nums[left], nums[right]); left++; right; } } };
Please note that:
 The array subscript starts from 0, so the K items on the left of the array are flipped from item 0 to item k1. The same is true for the right side of the array.
 The k value may be greater than the array length N, that is, the whole array is moved k/n times, and then moved k%n times to get the answer. So here we want to set k as k%n.
Complexity analysis
Time complexity: O(n). In addition to the global flip and the subsequent two respective flips, each element in the array is flipped twice, so the time complexity is O(2n)=O(n).
Space complexity: O(1), we only need constant space to store several variables.
Reference results
Accepted 38/38 cases passed (28 ms) Your runtime beats 49.29 % of cpp submissions Your memory usage beats 91.94 % of cpp submissions (24.2 MB)
Method 3: in situ solution
Method 1 uses additional arrays to make the space complexity reach O(n); Method 2 traverses each element in the array twice, and the time complexity is O(2n)=O(n). Is there any way to reduce the space complexity to constant space and only need to traverse the array elements once? The answer is yes.
We can optimize from method 1. In method 1, our operation on each element is to "put the element directly in its final position". There is no problem with this idea, but the problem lies in our method of traversing elements, which is the fundamental reason why we use additional arrays.
In method 1, when the ith element is processed, that is, placed at the position (i+k)%n, the selection strategy of the next element to be processed is sequential selection, that is, the i+1 element. Under this strategy, the elements originally placed at (i+k)%n are not only overwritten, but also directly discarded. That's why we need the original array to record what was in each position, and then write the results to a new array. Therefore, to optimize method 1, we need to change the selection strategy of the next element to be processed.
Method 3 begins to be clear. We put the ith element at position (i+k)%n and cover the element at that position. Therefore, we should take the (i+k)%n position as the element to be processed, save it, put it at the (i+2*k)%n position, and so on.
Taking nums=[1,2,3,4,5,6,7], k=3 as an example, the transformation process of the array is as follows:
It can be found that one round of traversal can complete the flip of the array. The end condition of the loop is also very simple, that is, the first item of the array is accessed. But let's focus on another example: num = [ 1,  100,3,99], k=2. It can be found that a round of traversal can only exchange  1 and 3. From this, we can conclude that:

When the array length n cannot be divided by k, a round of traversal must be able to exchange all data;

When n can be divided by k, the number of round s exchanged is the greatest common divisor (gcd) of N and k.
So far, the number of cycles of the first layer can be determined as the number of rounds of exchange round. Next, we need to determine the number of exchanges in a round (count). In the case of non divisible (count = = 1), we need to exchange n times per round, that is, one round of exchange is completed; For the case of integer division (count! = 1), we can only exchange n/round times in a round.
Namely:
c
o
u
n
t
=
{
n
+
1
r
o
u
n
d
=
1
n
/
r
o
u
n
d
r
o
u
n
d
≠
1
count= \left\{\begin{matrix} n+1 & round=1 \\ n/round & round \neq 1 \end{matrix}\right.
count={n+1n/roundround=1round=1
Here are some process demonstrations of other examples:
nums=[1,100,3,99]，k=2:
nums=[1,2,3,4,5,6]，k=2:
nums=[1,2,3,4,5,6]，k=3:
#include <vector> #include <numeric> using namespace std; class Solution { public: void rotate(vector<int> &nums, int k) { int n = nums.size(); k %= n; if (k == 0) return; int round = gcd(n, k); int count = round == 1 ? n + 1 : n / round; for (int i = 0; i < round; i++) { int last = nums[i]; for (int j = 1; j <= count; j++) { swap(last, nums[(i + j * k) % n]); } } } };
Complexity analysis
Time complexity: O(n). N is the length of the array, and each element will be traversed only once.
Space complexity: O(1), we only need constant space to store several variables.
Reference results
Accepted 38/38 cases passed (20 ms) Your runtime beats 92.01 % of cpp submissions Your memory usage beats 98.33 % of cpp submissions (24.2 MB)
Animation powered by ManimCommunity/manim