LeetCode刷题日记-小殷同学

动态规划
链表
位运算
回文子串:最长回文子串,删掉一个字符变为回文串

动态规划

198.打家劫舍
题目: 一排房屋,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
解法:动态规划。 dp[i]存放偷到第i个房子时的最大金额,转移方程dp[i] = max(dp[i-1], dp[i-2] + nums[i]).
如果偷第i个那么第i-1个肯定不偷,只要看dp[i-2] + nums[i]是不是比dp[i-1]大就可以了。

int rob(vector<int>& nums) {
        if(nums.size() == 0)    return 0;
        if(nums.size() == 1)    return nums[0];
        if(nums.size() == 2)    return max(nums[0], nums[1]);
        vector<int> dp(nums.size(), 0);
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for(int i=2; i < nums.size(); i++){
            if(dp[i-1] > dp[i-2] + nums[i]){
                dp[i] = dp[i-1];
            }
            else{
                dp[i] = dp[i-2] + nums[i];
            }
        }
        return dp[nums.size() - 1];
    }

进阶版:房屋首尾相连 213. 打家劫舍 II
二维,dp[0][i]表示不偷第一家,dp[1][i]表示偷第一家,最后一家的时候分开讨论。

int rob(vector<int>& nums) {
        if(nums.size() == 0)    return 0;
        if(nums.size() == 1)    return nums[0];
        if(nums.size() == 2)    return max(nums[0], nums[1]);
        vector<vector<int>> dp(2, vector<int>(nums.size(), 0));
        dp[0][0] = 0;
        dp[0][1] = nums[1];
        dp[1][0] = nums[0];
        dp[1][1] = nums[0];
        for(int j = 0; j < 2; j++){
            for(int i=2; i < nums.size()-1; i++){
                if(dp[j][i-1] > dp[j][i-2] + nums[i]){
                    dp[j][i] = dp[j][i-1];
                }
                else{
                    dp[j][i] = dp[j][i-2] + nums[i];
                }
            }
        }
        dp[0][nums.size() - 1] = max(dp[0][nums.size() - 2], dp[0][nums.size() - 3] + nums[nums.size() - 1]);
        dp[1][nums.size() - 1] = dp[1][nums.size() - 2];
        return max(dp[0][nums.size() - 1], dp[1][nums.size() - 1]);
        

    }

41. 缺失的第一个正数
题目:给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?

解法1:哈希表
解法2:置换。
step1: 扫描数组,如果x=nums[i],那么nums[i]应该放在nums[x-1]处。直到nums[i]不在[1,n]的范围内,扫下一个数。
step2: 扫描数组,如果nums[i] != i+1,那么返回i+1, 如果扫完一边都符合,返回n+1

int firstMissingPositive(vector<int>& nums) {
        for(int i=0; i < nums.size(); i++){
            while(nums[i] >0 && nums[i] <= nums.size() && nums[i] != nums[nums[i]-1]){
                int temp = nums[nums[i]-1];
                nums[nums[i]-1] = nums[i];
                nums[i] = temp;
            }
        }
        for(int i=0; i < nums.size(); i++){
            if(nums[i] != i+1)  return i+1;
        }
        return nums.size()+1;
    }

链表

142. 环形链表 II
题目:给你个链表,返回环的入口结点
官方解法:a+(n+1)

b+nc=2(a+b)⟹a=c+(n−1)(b+c),快慢指针相遇后,额外使用一个指针 ptr。起始,它指向链表头部;随后,它和slow 每次向后移动一个位置。最终,它们会在入环点相遇。
在这里插入图片描述

解法2:快慢指针 先找到环中有多少节点,然后相当于求链表倒数第n个节点(采用滑动窗口),代码如下。

class Solution {
public:
    ListNode *find_node(ListNode *head, int n){
        ListNode *begin = head, *end = head;
        while(--n){
            end = end->next;
        }
        while(end->next != begin){
            // cout << begin->val << '\t' << end->val << endl;
            begin = begin->next;
            end = end->next;
        }
        return begin;
    }
    ListNode *detectCycle(ListNode *head) {
        if(!head || !head->next)   return nullptr;
    
        ListNode *slow = head;
        ListNode *quick = head->next;
        int count = 1;
        while(quick!=slow){
            quick = quick->next;
            if(!quick)  return nullptr;
            quick = quick->next;
            if(!quick)  return nullptr;
            slow = slow->next;
            count++;
        }
        // cout << count << endl;
        ListNode *temp = find_node(head, count);
        return temp;
    }
};

141. 环形链表
题目:给你个链表,判断有没有环
快慢指针「Floyd 判圈算法」(又称龟兔赛跑算法)
定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head && !head->next) return false;
        if(!head)   return false;

        ListNode *slow = head;
         ListNode *quick = head->next;
         while(quick != slow ){
             quick = quick->next;
             if(!quick) return false;
             quick = quick->next;
             if(!quick) return false;
             slow = slow->next;
         }
         return true;
    }
};

位运算

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值