LeetCode题解——双指针(二)

88. 合并两个有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

直接插入

从nums1中倒序找到nums2[i]的插入位置,然后插入,遍历所有nums2[i],即合并成功。
因为两个数组都是递增的,倒序找更快。不要小看这种方法,也是非常快的,而且空间复杂度为O(1).

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i = 0, j = m - 1;
        int n1 = j;
        while(i < n)
        {
            while(j >= 0) if(nums1[j] > nums2[i]) j--; else break;
            for(int k = n1; k >= j+1; k--)
            {
                nums1[k+1] = nums1[k];
            }
            nums1[j+1] = nums2[i];
            n1++;
            i++;
            j = n1;
        }
    }
};

双指针

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int p1 = m - 1, p2 = n - 1, p = m + n -1;
        while(p1 >= 0 && p2 >= 0)
        {
            nums1[p--] = (nums1[p1] < nums2[p2]) ? nums2[p2--] : nums1[p1--];
        }
        // nums2可能有剩余,将剩余的添加到nums1中。
        for(int i = 0; i <= p2; i++)
            nums1[i] = nums2[i];
    }
};


从提交结果来看,第二种方法比第一种方法慢一点。

141. 环形链表

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

双指针

一快一慢指针,在有环的情况下,快指针会追上慢指针,反之无环。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL)
            return false;
        ListNode *p = head, *q = head;
        int flag = false;
        while(p->next != NULL && q->next != NULL)
        {
            p = p->next;
            if(q->next->next != NULL)
                q = q->next->next;
            else
                break;
            if(p == q)
            {
                flag = true;
                break;
            }
        }
        return flag;
    }
};

524. 通过删除字母匹配到字典里最长单词

给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:
s = “abpcplea”, d = [“ale”,“apple”,“monkey”,“plea”]

输出:
“apple”
示例 2:

输入:
s = “abpcplea”, d = [“a”,“b”,“c”]

输出:
“a”
说明:

所有输入的字符串只包含小写字母。
字典的大小不会超过 1000。
所有输入的字符串长度不会超过 1000。

暴力匹配1

先对d按首字母大小排序,然后直接匹配,找到匹配成功字符串最长的那个。

class Solution {
public:
    string findLongestWord(string s, vector<string>& d) {
        sort(d.begin(), d.end());
        int max = 0, ans = -1, i = 0;
        for(i = 0; i < d.size(); ++i)
        {
            int j = 0, n = d[i].length(), k = 0, flag = 0;
            while(j < s.length() && k < n)
            {
                if(s[j] == d[i][k])
                    j++, k++;
                else
                    j++;
                if(k == n)
                    flag = 1;
            }
            if(flag && max < n)
                max = n, ans = i;
        }
        return ans != -1 ? d[ans] : "";
    }
};

暴力匹配2

不用排序,每次记录匹配成功的字符串,跟下一次比较取最长且首字母最小的那个。

class Solution {
public:
    bool is_seq(string a, string b) // 判断b是不是a的字符串
    {
        int j = 0;
        for(int i = 0; i < a.length() && j < b.length(); ++i)
            if(a[i] == b[j])
                j++;
        return j == b.length();
    }
    string findLongestWord(string s, vector<string>& d) {
        string max = "";
        for(string s1 : d)
            if(is_seq(s, s1) && (max.length() < s1.length() || (max.length() == s1.length() && max > s1)))
                max = s1;
        return max;
    }
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值