leetcode刷题_day4

142.Linked List Cycle(Medium)

  1. 对于链表找环路的问题,之前没有涉及过,参考答案如下:
    有一个通用的解法,快慢指针(Floyd判圈法)。给定两个指针,分别命名为slow和fast,起始位置在链表的开头,每次fast前进两步,slow前进一步,如果fast可以走到尽头,那么说明没有环路;如果fast可以无限走下去,那么说明一定有环路,且一定存在一个时刻,slow和fast相遇,当slow和fast第一次相遇时,将fast重新移动到链表开头,并且让slow和fast每次都前进一步,当slow和fast第二次相遇时,相遇的节点就是环路的开始点。
    附代码如下:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode * slow = head, * fast = head;
        do{
            if(!fast || !fast->next)
                return NULL;
            fast = fast->next->next;
            slow = slow->next;
        }while(fast!=slow);
        fast = head;
        while(fast!=slow)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return fast;

    }
};

76.Minimum Window Substring

(这道题可以被当作一道典型题记忆,滑动窗口法)
此题的解法为滑动窗口解法,看完题解之后,很快就知道大体思路,但是根据思路写代码,总还是会有一点卡壳的地方。记录一下滑动窗口法代码实现的全过程思路。

  1. 首先需要统计T子串中的词频数
vector<int> chars(128,0)
for(int i =0;i<T.size();++i){
    ++chars[T[i]];
}
//当单个字符被作为索引传入int类型的vector中时,实际上等同于
//char['a'] = char[97] 
//这种方式可以用来统计词频数
  1. 需要有一个表用来记录S中有哪些字符是T中的
    思考过后,如果没有这样一个表,后续使用滑动窗口,每次遍历词频数表的每一项势必会增加时间复杂度,所以这个表是需要的。
vector<bool> flag(128,false)
for(int i =0;i<T.size();++i){
    flag[T[i]] = true;
  1. 有哪些变量需要定义,为什么?
    需要一个滑动窗口左边界,滑动窗口右边界,最小字串的左边界,最小子串的右边界。初始化时,滑动窗口左右边界,最小窗口左边界都初始化为0,最小窗口右边界初始化为S.size()+1,这个是为了之后判断如果遍历之后最小窗口的有边界依然为S.size()+1,就说明没有符合条件。
    还需要定义一个cnt变量,这个变量是为了满足题目中时间复杂度为O(n)而设立的,如果不设一个总量(窗口中包含T中字符个数,上限为T.size()),必然要每次遍历chars数组,看有没有都小于0(取一个,chars减一)。

  2. 总体思路

  • 滑动窗口右边界一直向右走
  • 取完的子串正好包含T停止,如果子串长度小于最小子串的长度,把左右边界给最小子串长度。
  • 滑动窗口左边界开始向右走,走到cnt的总数不等于T子串的长度停止(此时正好脱离)
  • 右边界继续向右走寻找下一个刚刚被删去的字符(这也是寻找新子串的过程)
  • 找到新子串就和原来的最小子串长度相比较,小了就赋值给最小子串,大了就继续找
  • 找到结尾停止。
class Solution {
public:
    string minWindow(string S, string T) {
        vector<int> chars(128, 0);
        vector<bool> flag(128, false);
        //先统计T中字符的频数
        for (int i = 0; i < T.size(); ++i) {
            flag[T[i]] = true;
            ++chars[T[i]];
        }
        //移动窗口,不断更新统计数据
        //尝试将l向右移动,在不影响结果的情况下获得最短字符串
        int cnt = 0, l = 0, min_l = 0, min_size = S.size() + 1;
        for (int r = 0; r < S.size(); ++r) {
            if (flag[S[r]]) {
                if (--chars[S[r]] >= 0) {
                    ++cnt;
                }
        }
            while (cnt == T.size()) {
                if (r - l + 1 < min_size) {
                    min_l = l;
                    min_size = r - l + 1;
                }
                if (flag[S[l]] && ++chars[S[l]] > 0) {
                    --cnt;
                }
                ++l;
            }
        }
        return min_size > S.size() ? " " : S.substr(min_l, min_size);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值