力扣题目训练(3)

2024年1月27日力扣题目训练

  • 2024年1月27日力扣题目训练
    • 290. 单词规律
    • 292. Nim 游戏
    • 303. 区域和检索 - 数组不可变
    • 91. 解码方法
    • 92. 反转链表 II
    • 41. 缺失的第一个正数

2024年1月27日力扣题目训练

2024年1月27日第三天编程训练,今天主要是进行一些题训练,包括简单题3道、中等题2道和困难题1道,昨天没有做完,自制力还是不行,我写这个的初衷只是为了记录自己每天干了什么,希望能坚持下去。

290. 单词规律

链接: 丑数
难度: 简单
题目:力扣题目训练(3)_第1张图片
运行示例:
力扣题目训练(3)_第2张图片
思路:
由题目可知,这是一个映射关系,可以利用哈希表来做,但是只用一个哈希表无法完成双向绑定的效果故需要利用两个哈希表。
代码:

class Solution {
public:
    bool wordPattern(string pattern, string s) {
        unordered_map<char,string> map;
        unordered_map<string,char> rmap;
        vector<string> vtr;
        int t =-1;
        for(int i = 0 ; i < s.size(); i++){
           if(s[i] == ' '){
               t += 1;
               vtr.push_back(s.substr(t,i-t));
               t = i;
           }
        }
        vtr.push_back(s.substr(t+1,s.size()-1));
        int n = pattern.size();
        int m = vtr.size();
        if(m != n) return false;
        for(int i = 0; i < n; i++){
            map[pattern[i]] = vtr[i];
            rmap[vtr[i]] = pattern[i];
        }
        for(int i = 0; i < n; i++){
            if( map[pattern[i]] != vtr[i] || pattern[i] != rmap[vtr[i]]) return false;
        }
        return true;
    }
};

292. Nim 游戏

链接: 游戏
难度: 简单
题目:
力扣题目训练(3)_第3张图片
运行示例:
力扣题目训练(3)_第4张图片

思路:
数学问题,当自己面对4块石头时,无论怎样都无法胜出,故需避免总的石头数目为 4 的倍数。
代码:

class Solution {
public:
    bool canWinNim(int n) {
        return n%4 != 0;
    }
};

303. 区域和检索 - 数组不可变

链接: 区域和检索
难度: 简单
题目:
力扣题目训练(3)_第5张图片
运行示例:
力扣题目训练(3)_第6张图片

思路:
这道题目如果单纯的用循环相加也能做,但是很有可能时间超过,所以我采用的是求前项和,要求指定区间内的和可以相减即可。
代码:

class NumArray {
public:
    vector<int> sums;
    NumArray(vector<int>& nums) {
        sums.push_back(nums[0]);
        for(int i = 1; i < nums.size(); i++){
            sums.push_back(sums[i-1]+nums[i]);
        }

    }
    
    int sumRange(int left, int right) {
        if(left == 0) return sums[right];
        return sums[right]-sums[left-1];
    }
};

91. 解码方法

链接: 解码
难度: 中等
题目:
力扣题目训练(3)_第7张图片
运行示例:
力扣题目训练(3)_第8张图片

思路:
我是用递归做的,结果时间超过了。我看了解析是用动态规划做的,原因是当前字母的解码方法可以看做前面的解码方方法加上这个字母的解码方法。f[i]可以看作字符串 s的前 i个字符 s[1…i]s[1…i]s[1…i] 的解码方法数。
代码:

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> f(n+1);
        f[0] = 1;
        for(int i = 1; i <= n; i++){
            if(s[i-1] != '0'){
                f[i] += f[i-1];
            }
            if(i > 1 && s[i - 2] != '0' && ((s[i - 2] - '0') * 10 + (s[i - 1] - '0') <= 26)  ){
                f[i] += f[i-2];
            }
        }
        return f[n];
    }
};

92. 反转链表 II

链接: 反转链表
难度: 中等
题目:
力扣题目训练(3)_第9张图片
运行示例:
力扣题目训练(3)_第10张图片
思路:
一次遍历的话就用头插法进行实现,注意给的head是不带头指针的,所以为了方便起见可以创建一个带头指针的链表。
代码:

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(left >= right) return head;
        ListNode *dummyNode = new ListNode(-1);
        dummyNode->next = head;
        ListNode*p,*q,*curr;
        p = dummyNode;
        for(int i = 0; i < left-1; i++){
            p = p->next;
        }
        curr = p->next;
        for(int i = 0; i < right - left; i++){
            q = curr->next;
            curr->next = q->next;
            q->next = p->next;
            p->next = q;
        }
        return dummyNode->next;
    }
};

41. 缺失的第一个正数

链接: 缺失的正数
难度: 困难
题目:
力扣题目训练(3)_第11张图片

运行示例:

力扣题目训练(3)_第12张图片

思路:
对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中.我用的是哈希表的思路,但是空间复杂度不符合题意。我看了题解,他们用的是置换和搞一个标记。置换是指将出现过的的整数置换到数组的对应位置,大于n+1的直接舍弃。搞一个标记即对出现过的整数在数组对应位置上加一个负号,然后遍历第一个是正数的位置即为结果。

代码:
置换:

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0; i < n; i++){
            while(nums[i] > 0 && nums[i] <= n && nums[nums[i] -1 ] != nums[i]){
                swap(nums[nums[i] - 1], nums[i]);
            } 
        }
        for(int i = 0; i < n; i++){
            if(nums[i] != i+1){
                return i + 1;
            }
        }
        return n + 1;
    }
};

标记

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0; i < n; i++){
            if(nums[i] <= 0){
                nums[i] = n + 1;
            }
        }
        for(int i = 0; i < n; i++){
            int num = abs(nums[i]);
            if(num <= n){
                nums[num - 1] = -abs(nums[num - 1]);
            }
        }
        for(int i = 0; i < n; i++){
            if(nums[i] > 0 ){
                return i + 1;
            }
        }
        return n + 1;
    }
};

你可能感兴趣的:(编程学习,leetcode,算法,c++)