力扣刷题【12.09】

21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* preHead = new ListNode(-1);

        ListNode* prev = preHead;
        while(list1 != nullptr && list2 != nullptr){
            if(list1->val < list2->val){
                prev->next=list1;
                list1=list1->next;
            }
            else{
                prev->next=list2;
                list2=list2->next;
            }
            prev = prev->next;
        }
        prev->next = list1==nullptr?list2:list1;
        return preHead->next;
    }
};

递归

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == NULL) {
            return l2;
        }
        if (l2 == NULL) {
            return l1;
        }
        if (l1->val <= l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        l2->next = mergeTwoLists(l1, l2->next);
        return l2;
    }
};

二分 35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4

返回第一个大于等于target的下标,或者nums.size()

  • 因为要找的是 大于等于target的,所以if(nums[mid]<target) l=mid+1;(mid之前的都小于target,所以下次的范围直接从mid+1开始)
  • 因为题目还可能出现nums.size(),所以r的初始化为nums.size()
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l=0,r=nums.size();
        int mid;
        while(l<r){
            mid=(l+r)>>1;
            if(nums[mid]>=target) r=mid;
            else if(nums[mid]<target) l=mid+1;

        }
        return l;
    }
};

详细二分题解力扣 对二分查找不是套模板并往里面填空,需要仔细分析题意

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]
示例 2:
输入:n = 1
输出:[“()”]

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        //dp[i]:i对括号组成的集合
        //思路:符合条件的左边肯定是左括号,后面一定有与之匹配的右括号
        //"("+ ... + ")"+...
        if(n==0) return {};
        if(n==1) return {"()"};
        vector<vector<string>> dp(n+1);
        dp[0]={""};
        dp[1]={"()"};
        for(int i=2;i<=n;i++)
            for(int j=0;j<i;j++)//i个括号
                for(string p:dp[j])//i个括号又分成了j+(i-j-1)+1
                    for(string q:dp[i-j-1]){
                        string str="("+p+")"+q;
                        dp[i].push_back(str);
                    }
        
        return dp[n];
    }
};

27. 移除元素

模板
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

[l, -1]的元素都是等于target

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if(nums.size()==0) return 0;
        if(nums.size()==1){
            if(nums[0]==val) return 0;
            else return 1;
        }
        //双指针
        int l=0,r=nums.size()-1;
        while(l<=r){
            if(nums[r]!=val && nums[l]==val) 
                swap(nums[l],nums[r]);
            if(nums[r]==val) r--;
            if(nums[l]!=val) l++;
        }

        return l;
    }
};

72. 编辑距离

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

class Solution {
public:
    int minDistance(string word1, string word2) {
        //dp[i][j]: s1的前i个变为s2的前j个需要的最小操作数
        int n1=word1.size(),n2=word2.size();
        vector<vector<int>> dp(n1+1,vector<int>(n2+1,0));

        for(int i=0;i<=n2;i++)
            dp[0][i]=i;
        for(int i=0;i<=n1;i++)
            dp[i][0]=i;//dp[0]是没有用的

        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                if(word1[i-1]!=word2[j-1])//注意下标和dp[i][j]里的ij之间的区别
                    dp[i][j]=min(dp[i-1][j]+1,min(dp[i-1][j-1]+1,dp[i][j-1]+1));
                else
                    dp[i][j]=dp[i-1][j-1];
            }
        }
        return dp[n1][n2];
    }
};

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:
输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以由 “leet” 和 “code” 拼接成。
示例 2:
输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以由 “apple” “pen” “apple” 拼接成。
注意,你可以重复使用字典中的单词。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> p;
        for(string tmp: wordDict){
            p.insert(tmp);
        }
        //dp[i]:s的前i个字符是否能被空格拆分成若干个字典中出现的单词
        int n=s.size();
        vector<bool> dp(n+1);
        dp[0]=true;
        for(int i=1;i<=n;i++){
            for(int j=0;j<i;j++){
                dp[i]=dp[j] && (p.find(s.substr(j,i-j))!=p.end());
                if(dp[i]) break;
            }
        }
        return dp[n];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值