zoukankan      html  css  js  c++  java
  • (二)双指针(C++刷题)

    三数之和

    Leetcode:https://leetcode-cn.com/problems/3sum/

    1.问题描述

    给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0?找出所有和为0且不重复的三元组。

    2.输入输出

    • 输入:nums=[-1,0,1,2,-1,-4]
    • 输出:[[-1,-1,2], [-1,0,1]]

    3.算法分析

    【排序+双指针】

    • 特判,对于数组长度 n,如果数组为null或者数组长度小于3,返回 [][]。
    • 对数组进行排序。
    • 遍历排序后数组:
      • 若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于0,直接返回结果。
        对于重复元素:跳过,避免出现重复解
      • 令左指针 L=i+1,右指针 R=n-1,当 L<R时,执行循环:
        • 当 nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
        • 若和大于 0,说明 nums[R] 太大,R 左移
        • 若和小于 0,说明 nums[L] 太小,L 右移
    • 时间复杂度:\(O(n^2)\)
    • 空间复杂度:\(O(1)\)

    4.编程实现

    #include <iostream> 
    #include <algorithm>
    #include <vector> 
    using namespace std; 
    
    
    class Solution{
    public:
        vector<vector<int>> threeSum(vector<int>& nums){
            vector< vector<int> > ans;
            if(nums.size() < 3 || nums.empty()) return ans; // 特判
            int n = nums.size();
        
            sort(nums.begin(), nums.end()); //排序
            for(int i = 0; i < n; i++)  // 枚举最小值
            {
                if(nums[i] > 0) return ans;
                if(i > 0 && nums[i] == nums[i-1]) continue;   // 最小元素去重!
                int l = i+1;
                int r = n-1;
                while(l < r)    // 枚举中间值和最大值
                {
                    int x = nums[l] + nums[r] + nums[i];
                    if(x == 0){ // 符合条件,存储,并且去重,双端都移到下一个位置
                        ans.push_back({ nums[i], nums[l], nums[r] });
                        while( l < r && nums[l] == nums[l+1]) l++; l++;
                        while( l < r && nums[r] == nums[r-1]) r--; r--;
                    }
                    else if(x > 0) // 大了就让右边最大值变小
                        r--;
                    else        // 小了就让左边中间值变大
                        l++;
                }
            }
            return ans;
        }
    };
    
    int main() { 
        int get;
        Solution sol;
        vector<int> nums; 
        
        getchar();
        while (cin >> get) { 
            nums.push_back(get); 
            if (cin.get() == ']') break; 
        } 
        
        cout << sol.threeSum(nums)[0][0] << endl; 
        return 0; 
    
    } 
    

    无重复字符的最长子串

    Leetcode:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

    1.问题描述

    给定一个字符串s,找出其中不含有重复字符的最长子串的长度。

    2.输入输出

    • Input:"abcabcbb"
    • Output:3

    3.算法分析

    滑动窗口:核心思想就是从每一个字符开始,找到不包含重复字符的最长子串。每次移动区间的起点或者终点,直到起点的值等于终点的值。

    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    4.编程实现

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            int start(0), end(0), length(0), result(0);
            int nSize = s.size();
            
            while (end < nSize) {  // 终点
                char tmpChar = s[end];
                for (int index = start; index < end; index++) {
                    if (tmpChar == s[index]) {
                        start = index + 1;
                        length = end - start;
                        break;
                    }
                }
                end++;
                length++;
                result = max(result, length);
            }
            
            return result;
        }
    };
    
    int main() {
        Solution sol;
        string s;
        cin >> s;
        
        cout << sol.lengthOfLongestSubstring(s) << endl;
        return 0;
    }
    

    合并两个有序数组

    Leetcode:88,https://leetcode-cn.com/problems/merge-sorted-array/

    1.问题描述

    给定两个有序数组,把两个数组合并为一个,将第二个数组归并到第一个数组上,
    不需要开辟额外空间。

    2.输入输出

    • Input:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
    • Output:[1, 2, 2, 3, 5, 6]

    3.算法分析

    两个指针放在数组的末尾,第三个指针定义pos,每次将较大的那个数字复制到第一个数组的后面,然后向前移动一位。

    • 时间复杂度:O(m+n)
    • 空间复杂度:O(1)

    4.编程实现

    #include <iostream>
    #include <vector>
    using namespace std;
    
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n){
    	int pos = m-- + n-- - 1;
    	while(m >= 0 && n >= 0){
    		nums1[pos--] = nums1[m] > nums2[n]? nums1[m--]: nums2[n--];
    	}
    	while(n >= 0){
    		nums1[pos--] = nums2[n--];
    	}
    }
    int main(){
    	vector<int> nums1;
    	nums1.push_back(1);
    	nums1.push_back(2);
    	nums1.push_back(3);
    	nums1.push_back(0);
    	nums1.push_back(0);
    	nums1.push_back(0);
    	
    	vector<int> nums2;
    	nums2.push_back(2);
    	nums2.push_back(5);
    	nums2.push_back(6);
    	
    	int m = 3;
    	int n = 3;
    	merge(nums1, m, nums2, n);
    	cout << nums1[4] << endl;
    } 
    
    本文为博主原创文章,未经博主允许禁止转载,需转载请注明出处,欢迎指正!
  • 相关阅读:
    PS 修复画笔
    PS 魔棒工具、仿制图章
    PS选区的应用
    PS界面介绍
    火狐浏览器任务栏设置默认 隐私模式开启
    [CSS] Using inline-grid to gain easy control over gap and size
    [AWS] Presign url for S3
    [CSS] Customer focus / disabled style for select element
    [CSS] Using single grid-template-area and justify-self to select arrow down icon in select
    [CSS 3] Using CSS attribute selector
  • 原文地址:https://www.cnblogs.com/caoer/p/15722354.html
Copyright © 2011-2022 走看看