leetcode面试经典150题1-5 |88合并两个有序数组 、27. 移除元素、26. 删除有序数组中的重复项、80. 删除有序数组中的重复项 II、169. 多数元素
88合并两个有序数组
题目
https://leetcode.cn/problems/merge-sorted-array/description/?envType=study-plan-v2&envId=top-interview-150
解法
- 【暴力实现】
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
if (n == 0) return;
for(int i = m; i < nums1.size(); i++){
nums1[i] = nums2[i-m];
}
sort(nums1.begin(),nums1.end());
return;
}
};
空间复杂度O(log(m+n)) : 排序序列长度
时间复杂度O(n+(m+n)log(m+n))
2.【双指针】
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int tmp1 =0, tmp2 = 0;
int result[m+n];
int temp;
while (tmp1 < m || tmp2 <n) {
if(tmp1 == m){
temp = nums2[tmp2++];
}
else if(tmp2 == n){
temp = nums1[tmp1++];
}
else if(nums1[tmp1]<nums2[tmp2]){
temp=nums1[tmp1++];
}
else{
temp = nums2[tmp2++];
}
result[tmp1+tmp2-1] = temp;
}
for (int i = 0; i < m+n; i++) {
nums1[i] = result[i];
}
}
};
时间复杂度 O(m+n)
空间复杂度O(m+n)
3.【逆行双指针】
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int tmp1 =m-1, tmp2 = n-1;
int num = m+n-1;
int temp;
while (tmp1 >= 0 || tmp2 >= 0) {
if(tmp1 == -1){
temp = nums2[tmp2--];
}
else if(tmp2 == -1){
temp = nums1[tmp1--];
}
else if(nums1[tmp1]>nums2[tmp2]){
temp=nums1[tmp1--];
}
else{
temp = nums2[tmp2--];
}
nums1[num--] = temp;
}
}
};
利用了该题的中num1后n个数没有值的特点
时间复杂度:O(m+n)
空间复杂度:O(1)
27. 移除元素
题目
https://leetcode.cn/problems/remove-element/description/?envType=study-plan-v2&envId=top-interview-150
解法
- 【暴力实现】
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int result = 0;
vector<int> nums1(nums.size());
for(int i = 0; i < nums.size(); i++){
if(nums[i] != val){
nums1[result++]=nums[i];
}
}
nums = nums1;
return result;
}
};
时间复杂度:O(n)
空间复杂度;O(n)
2.【快慢指针】
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowidx = 0;
for(int fastidx = 0; fastidx < nums.size(); fastidx++){
if(nums[fastidx] != val){
nums[slowidx++]=nums[fastidx];
}
}
return slowidx;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
26. 删除有序数组中的重复项
题目
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/?envType=study-plan-v2&envId=top-interview-150
解法
- 【暴力解法-双指针】没有利用序列排序的特点
时间复杂度:O(n^2)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 2) return nums.size();
int fast = 1;
int n = nums.size();
int slow = 0;
while(fast < n){
if(nums[slow] == nums[fast]){
for (int i = fast; i < n-1; i++){
nums[i] = nums[i+1];
}
n--;
}else{
fast++;
slow++;
}
}
return fast;
}
};
2.【双指针优化】利用序列的特点(具体问题具体分析)
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 2) return nums.size();
int fast = 1;
int n = nums.size();
int slow = 1;
while(fast < n){
if(nums[fast] != nums[fast-1]){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
80. 删除有序数组中的重复项 II
题目
https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/?envType=study-plan-v2&envId=top-interview-150
解法
- 【快慢指针】考虑开头条件和结尾条件,中间循环
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 2) return nums.size();
int fast = 1;
int slow = 1;
int n = nums.size();
while(fast < n){
if(nums[fast-1] != nums[fast] ||( fast < n-1 && nums[fast] != nums[fast+1]) ||(nums[fast-1] == nums[fast] && fast == n-1)){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
时间复杂度:O(n)
空间复杂度;O(n)
2.【双指针】充分利用序列是有序的,利用慢指针的特点(指针前的序列是有序的)
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 2) return nums.size();
int fast = 2;
int slow = 2;
int n = nums.size();
while(fast < n){
if(nums[slow-2] != nums[fast]){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
169. 多数元素
题目
https://leetcode.cn/problems/majority-element/description/?envType=study-plan-v2&envId=top-interview-150
解法
- 【暴力解法】使用unordered_map
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
int majorityElement(vector<int>& nums) {
std::unordered_map<int, int> map;
int num = 0;
int result = 0;
for(int i = 0; i < nums.size(); i++){
map[nums[i]]++;
}
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
if(it->second > num){
num = it->second;
result = it->first;
}
}
return result;
}
};
2.【Boyer-Moore 投票算法】
思路:如果我们把众数记为 +1,把其他数记为 −1,将它们全部加起来,显然和大于 0,从结果本身我们可以看出众数比其他数多。
时间复杂度:O(n)。Boyer-Moore 算法只对数组进行了一次遍历。
空间复杂度:O(1)。Boyer-Moore 算法只需要常数级别的额外空间。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate = -1;
int count = 0;
for(int num:nums){
if(num == candidate) count++;
else if(--count < 0){
candidate = num;
count++;
}
}
return candidate;
}
};