Question:
Given an array nums
, write a function to move all 0
's to the end of it while maintaining the relative order of the non-zero elements.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.
Solution 1:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
// find the number of Zeros
int numOfZeros = 0;
for (int i = 0; i < nums.size(); i++) {
numOfZeros += (nums[i] == 0);
}
// Make all non-zero elements retain their order
vector<int> ans;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
ans.push_back(nums[i]);
}
}
// Move all zeros to the end
while (numOfZeros--) {
ans.push_back(0);
}
// Combine the result
for (int i = 0; i < nums.size(); i++) {
nums[i] = ans[i];
}
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Solution 2: Two Pointers (Space Optimal)
Here we are gonna use two pointers. The slower one will keep tracking of the last non zero elements, and the faster one will go through all elements to see if that is a non-zero element. If so, the method will put it at the last found non zero place and replace the index.
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int lastNonZero = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
nums[lastNonZero++] = nums[i];
// here we asign first and then increment the lastNonZero
}
}
for (int i = lastNonZero; i < nums.size(); i++) {
nums[i] = 0;
}
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Solution 3: Optimal Solution
A simple realization is if the current element is non-0, its’ correct position can at best be it’s current position or a position earlier.
class Solution {
public:
void moveZeroes(vector<int>& nums) {
for (int lastNonZero = 0, cur = 0; cur < nums.size(); cur++) {
if (nums[cur] != 0) {
swap(nums[lastNonZero++], nums[cur]);
}
}
}
}
Space Complexity : O(1) Only constant space is used.
Time Complexity: O(n). However, the total number of operations are optimal. The total operations (array writes) that code does is Number of non-0 elements.This gives us a much better best-case (when most of the elements are 0) complexity than last solution. However, the worst-case (when all elements are non-0) complexity for both the algorithms is same.
75
Question:
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note: You are not suppose to use the library’s sort function for this problem.
Example:
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Solution 1: by using the same approach with 283
class Solution {
public:
void sortColors(vector<int>& nums) {
// first we put all 1 at the end of the array
for (int cur = 0, lastNonOne = 0; cur < nums.size(); cur++) {
if (!nums[cur] == 1){
swap(nums[lastNonOne++], nums[cur]);
}
}
// then we put all 2 at the end of the array
for (int cur = 0, lastNonTwo = 0; cur < nums.size(); cur++) {
if (!nums[cur] == 2) {
swap(nums[cur], nums[lastNonTwo]);
}
}
}
}
Solution 2
class Solution {
public:
void sortColors(vector<int>& nums) {
int zero = 0, second = nums.size()-1;
for(int i = 0; i <= second; i++) {
while(nums[i] == 2 && i < second) {
swap(nums[i], nums[second--]);
}
while (nums[i] == 0 && i > zero) {
swap(nums[i], nums[zero++]);
}
}
}
}
Note of Solution2:
- We need to make sure i < second when swap 2 to the end and i > zero when swap 0 to the front.
- We must check 2 first then check 0, because if we check 0 first, it is possible that we switch an 0 from the end of the array, but never get a chance to switch it back. However, since we are looping through the numbers from the beginning to the end, so all the looped 2 will be at the end of the array.