雙指針

一茂缚、雙指針總結(jié)

1.1題目

快慢指針(主要解決鏈表中的問題)

  • 141.環(huán)形鏈表
  • 142.環(huán)形鏈表 II
  • 876.鏈表的中間結(jié)點
  • 劍指 Offer 22. 鏈表中倒數(shù)第k個節(jié)點

左右指針

  • 704.二分查找
  • 167.兩數(shù)之和 II - 輸入有序數(shù)組
  • 15.三數(shù)之和(去重)
  • 11.盛最多水的容器

滑動窗口(兩個指針從一個起點出發(fā))

  • 209.長度最小的子數(shù)組
  • 76.最小覆蓋子串(hard)
  • 3.無重復(fù)字符的最長子串
  • 劍指 Offer 57 - II. 和為s的連續(xù)正數(shù)序列

1.2滑動窗口的思路

  • 1.不斷擴張窗口,尋找一個可行解蕾哟;
  • 2.不斷收縮窗口则披,優(yōu)化這個可行解共缕,直到不滿足條件;
  • 3.重復(fù)1士复、2图谷,即尋找下一個可行解,然后再優(yōu)化阱洪。

(適用于求最小的問題便贵,求最大的問題要改一下,不過代碼結(jié)構(gòu)差不多)

int left = 0, right = 0;

while (right < s.size()) {
    window.add(s[right]);

    while (valid) {
        window.remove(s[left]);
        left++;
    }
    right++;
}

稍微?煩的地?就是這個 valid 條件冗荸。

二承璃、題目

141.環(huán)形鏈表

思路1:哈希表

bool hasCycle(ListNode *head) {
    if (!head) return false;
    set<ListNode*> st;
    
    while (head) {
        if (st.count(head)) {
            return true;
        }else{
            st.insert(head);
            head = head->next;
        }
    }
    return false;
}

思路2:雙指針。
如果鏈表存在環(huán)蚌本,則快指針和慢指針一定會相遇盔粹。

bool hasCycle(ListNode *head) {
    ListNode *slow, *fast;
    slow = fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        
        if (slow == fast) return true;
    }
    return false;
}

142.環(huán)形鏈表 II

分析相遇時的情況:

從起點到環(huán)入口的路程記做a,環(huán)的長度記做b程癌;
快指針走的路程記做f舷嗡,慢指針走的路程記做s;
我們可以得到:
f = s + nb
f = 2s
  => s = nb  
  => s+a = 0+a

所以:當(dāng)快慢指針相遇時嵌莉,讓頭指針和慢指針同時開始走进萄,它們相遇的點就是環(huán)的入口。

ListNode *detectCycle(ListNode *head) {
    ListNode *slow, *fast;
    slow = fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) break;
    }
    // 沒有環(huán)
    if (!fast || !fast->next) return NULL;
    // 有環(huán)
    while (head != slow) {
        head = head->next;
        slow = slow->next;
    }
    return head;
}

876.鏈表的中間結(jié)點

題目描述:如果有兩個中間結(jié)點,則返回第二個中間結(jié)點中鼠。

該問題常常是以后題目的子問題可婶。注意兩點:

  • 快慢指針一起出發(fā)
  • 判斷條件(fast && fast->next)
ListNode* middleNode(ListNode* head) {
    ListNode *slow, *fast;
    slow = fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

劍指 Offer 22. 鏈表中倒數(shù)第k個節(jié)點

假設(shè) k 不會超過鏈表?度

ListNode* getKthFromEnd(ListNode* head, int k) {
    ListNode *slow, *fast;
    slow = fast = head;
    
    while (k--) fast = fast->next;
    
    while (fast) {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

704.二分查找

數(shù)組是升序的

int search(vector<int>& nums, int target) {
    int l = 0, r = nums.size()-1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (nums[mid] == target)
            return mid;
        else if(nums[mid] < target)
            l = mid + 1;
        else
            r = mid - 1;
    }
    return -1;
}

167.兩數(shù)之和 II - 輸入有序數(shù)組

vector<int> twoSum(vector<int>& nums, int target) {
    int l = 0, r = nums.size()-1;
    while (l < r) {
        int sum = nums[l] + nums[r];
        if (sum == target)
            return {l, r};
        else if (sum < target)
            l++;
        else
            r--;
    }
    return {};
}

15.三數(shù)之和

題目描述:給你一個包含 n 個整數(shù)的數(shù)組 nums,判斷 nums 中是否存在三個元素 a兜蠕,b扰肌,c 抛寝,使得 a + b + c = 0 熊杨?請你找出所有滿足條件且不重復(fù)的三元組。

思路

  • 固定一個數(shù)盗舰,對剩下的數(shù)組使用雙指針進行查找晶府。
  • 注意去重操作。
vector<vector<int>> threeSum(vector<int>& nums) {
    vector<vector<int>> ans;
    if (nums.size()<3) return ans;
    
    sort(nums.begin(), nums.end());
    for (int i=0; i<nums.size()-2; i++) {
        // 去重
        if (i>0 && nums[i] == nums[i-1]) {
            continue;
        }
        int l = i+1, r = nums.size()-1;
        int val = 0 - nums[i];
        while (l < r) {
            int temp = nums[l] + nums[r];
            if (temp == val) {
                vector<int> t = {nums[i], nums[l], nums[r]};
                ans.push_back(t);
                // 去重
                while (l<r && nums[l] == nums[l+1]) {
                    l++;
                }
                l++;
                // 去重
                while (l<r && nums[r] == nums[r-1]) {
                    r--;
                }
                r--;
            }else if (temp < val){
                l++;
            }else{
                r--;
            }
        }
    }
    return ans;
}

11.盛最多水的容器

左右哪邊小哪邊往中間移動

int maxArea(vector<int>& height) {
    int i = 0, j = height.size()-1;
    int maxArea = 0;

    while (i < j) {
        int temp = min(height[i],height[j]) * (j-i);
        maxArea = max(temp, maxArea);

        if (height[i] > height[j]) {
            j--;
        }else{
            i++;
        }
    }
    return maxArea;
}

兩個數(shù)組的交集 II

題目要求:結(jié)果中的元素應(yīng)與在兩個數(shù)組中出現(xiàn)的次數(shù)一致钻趋。
思路:先排序再雙指針川陆。

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    vector<int> ans;
    sort(nums1.begin(), nums1.end());
    sort(nums2.begin(), nums2.end());
    
    int p1 = 0, p2 = 0;
    int l1 = nums1.size(), l2 = nums2.size();
    while (p1 < l1 && p2 < l2) {
        int a = nums1[p1], b = nums2[p2];
        if (a == b) {
            ans.push_back(a);
            p1++; p2++;
        }else{
            a<b ? p1++ : p2++;
        }
    }
    return ans;
}

209.長度最小的子數(shù)組

題目描述:給定一個含有 n 個正整數(shù)的數(shù)組和一個正整數(shù) s ,找出該數(shù)組中滿足其和 ≥ s 的長度最小的連續(xù)子數(shù)組蛮位,并返回其長度较沪。如果不存在符合條件的子數(shù)組,返回 0失仁。

思路:因為是求連續(xù)子數(shù)組尸曼,所以可以用滑動窗口的方法。

  • 1.不斷擴張窗口萄焦,尋找一個可行解控轿;
  • 2.不斷收縮窗口,優(yōu)化這個可行解拂封,直到不滿足條件茬射;
  • 3.重復(fù)1、2冒签,即尋找下一個可行解在抛,然后再優(yōu)化。
int minSubArrayLen(int s, vector<int>& nums) {
    int lens = nums.size();
    if (lens==0) return 0;
    
    int l = 0, r = l;
    int sum = 0, ans = INT_MAX;
    while (r < lens) {
        sum += nums[r];
        r++;
        
        while (sum >= s) {
            ans = min(ans, r-l);
            sum -= nums[l];
            l++;
        }
    }
    // 考慮sum(nums)<s的情況
    return ans==INT_MAX ? 0: ans;
}

76.最小覆蓋子串

思路:和上題滑動窗口的思路一樣萧恕。只是判斷條件麻煩了點刚梭。

如何判斷 當(dāng)前窗口 包含T中的所有字符?

  • ??個哈希表 needs 記錄t中包含的字符及次數(shù)廊鸥;
  • ?另?個哈希表 window 記錄當(dāng)前窗?中包含的t中的字符及次數(shù)望浩。

使用一個變量 match 保存 window 滿足 needs 的個數(shù),如果 match 等于 needs惰说,則當(dāng)前窗口滿足條件磨德。

string minWindow(string s, string t) {
    int start = 0, minLen = INT_MAX;
    int l = 0, r = 0;
    
    unordered_map<char, int> needs;
    unordered_map<char, int> windows;
    for (char c: t) needs[c]++;
    
    int match = 0;
    while (r < s.size()) {
        // 不斷擴大窗口
        char c1 = s[r];
        if (needs.count(c1)) {
            windows[c1]++;
            if (windows[c1] == needs[c1]) {
                match++;
            }
        }
        r++;
        
        // 如果窗口符合條件,不斷收縮窗口
        while (match == needs.size()) {
            if (r - l < minLen) {
                minLen = r - l;
                start = l;
            }
            
            char c2 = s[l];
            if (needs.count(c2)) {
                windows[c2]--;
                if (windows[c2] < needs[c2]) {
                    match--;
                }
            }
            l++;
        }
    }
    return minLen == INT_MAX ? 0: s.substr(start, minLen);
}

3.無重復(fù)字符的最長子串

思路:

  • 1.擴大窗口,尋找最長的子串
  • 2.如果遇到重復(fù)的情況典挑,縮小子串酥宴,直到滿足條件
  • 3.重復(fù)1、2您觉,直到最后拙寡。
int lengthOfLongestSubstring(string s) {
    int l = 0, r = l;
    int ans = 0;
    unordered_map<char, int> map;
    while (r < s.size()) {
        char c1 = s[r];
        map[c1]++;
        r++;
        
        while (map[c1] > 1) {
            char c2 = s[l];
            map[c2]--;
            l++;
        }
        ans = max(ans, r-l);
    }
    return ans;
}

劍指 Offer 57 - II. 和為s的連續(xù)正數(shù)序列

題目描述:
輸入一個正整數(shù) target ,輸出所有和為 target 的連續(xù)正整數(shù)序列(至少含有兩個數(shù))琳水。
序列內(nèi)的數(shù)字由小到大排列肆糕,不同序列按照首個數(shù)字從小到大排列。

示例:

輸入:target = 9
輸出:[[2,3,4],[4,5]]
vector<vector<int>> findContinuousSequence(int target) {
    vector<vector<int>> ans;
    int l = 1, r = l;
    int sum = 0;
    while (r < target) {
        sum += r;

        while (sum >= target) {
            if (sum == target && r-l+1 >= 2) {
                vector<int> temp;
                for (int i=l; i<=r; i++) {
                    temp.push_back(i);
                }
                ans.push_back(temp);
            }
            sum -= l;
            l++;
        }
        r++;
    }
    return ans;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末在孝,一起剝皮案震驚了整個濱河市诚啃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌私沮,老刑警劉巖始赎,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仔燕,居然都是意外死亡造垛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門晰搀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來五辽,“玉大人,你說我怎么就攤上這事厕隧”计辏” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵吁讨,是天一觀的道長髓迎。 經(jīng)常有香客問我,道長建丧,這世上最難降的妖魔是什么排龄? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮翎朱,結(jié)果婚禮上橄维,老公的妹妹穿的比我還像新娘。我一直安慰自己拴曲,他們只是感情好争舞,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澈灼,像睡著了一般竞川。 火紅的嫁衣襯著肌膚如雪店溢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天委乌,我揣著相機與錄音床牧,去河邊找鬼。 笑死遭贸,一個胖子當(dāng)著我的面吹牛戈咳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壕吹,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼著蛙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了算利?” 一聲冷哼從身側(cè)響起册踩,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤泳姐,失蹤者是張志新(化名)和其女友劉穎效拭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胖秒,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡缎患,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了阎肝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挤渔。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖风题,靈堂內(nèi)的尸體忽然破棺而出判导,到底是詐尸還是另有隱情,我是刑警寧澤沛硅,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布眼刃,位于F島的核電站,受9級特大地震影響摇肌,放射性物質(zhì)發(fā)生泄漏擂红。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一围小、第九天 我趴在偏房一處隱蔽的房頂上張望昵骤。 院中可真熱鬧,春花似錦肯适、人聲如沸变秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹦玫。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钳垮,已是汗流浹背惑淳。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饺窿,地道東北人歧焦。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像肚医,于是被迫代替她去往敵國和親绢馍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344