当前位置: 首页 > news >正文

10.1刷题计划一

力扣33题   搜索旋转排序数组

设x=nums[mid]是我们现在二分取到的数,需要判断x和target的位置关系。

(1)如果x和target在不同的递增段:

1.如果target在第一段,x在第二段,说明target在x在左边。

2.如果x在第一段,target在第二段,说明target在x在右边。

(2)如果x和target在相同的递增段:

和lowerbound函数一样,比较x和target的大小即可。

下面代码用的开区间二分,用其他二分写法也是可以的。

二分的范围可以是(-1,n-1),也就是闭区间[0,n-2]。

如果target=nums[n-1],那么下面代码每次循环更新的都是left,而right始终不变。循环结束后,答案自然就是n-1了。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int last = nums.back();
        int left = -1,right  = nums.size()-1;   //开闭间(-1,n-1)
        while(left+1<right){             //开区间不为空
            int mid = left+(right-left)/2;
            int x = nums[mid];
            if(target>last && x<=last){       //target在第一段,x在第二段
                right = mid;                  //下轮循环去左边找
            }else if(x>last && target <= last){      //x在第一段,target在第二段
                left = mid;                   //下轮循环去右边找
            }else if(x>=target){              //否则,x和target在同一段
                right = mid;
            }else{
                left = mid;
            }
        }
        return nums[right] == target ? right : -1;
    }
};
 
 
力扣64题  最小路径和
动规五部曲
本题思路和力扣62题差不多
需要的是最小的路径和,所以状态转移方程就是dp[i][j]=min(dp[i-1][j]+grid[i][j],dp[i][j-1]+grid[i][j])
class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        vector<vector<int>>dp(grid.size(),vector<int>(grid[0].size()));
 
        dp[0][0] = grid[0][0];
        for(int i=1;i<grid.size();i++) dp[i][0] = dp[i-1][0]+grid[i][0];
        for(int i=1;i<grid[0].size();i++) dp[0][i] = dp[0][i-1]+grid[0][i];

        for(int i=1;i<grid.size();i++){
            for(int j=1;j<grid[0].size();j++){
                dp[i][j] = min(dp[i-1][j]+grid[i][j],dp[i][j-1]+grid[i][j]);
            }
        }
        return dp[grid.size()-1][grid[0].size()-1];
    }
};
 
力扣75题 颜色分类
需要进行两次遍历,使用两个指针分别用来交换0和1。
用指针p0来交换0,p1来交换1,初始值为0。
当我们从左向右遍历整个数组的时候。
如果找到了1,那么将其与nums[p1]进行交换,并将p1向后移动一个位置,与方法一相同。
如果找到了0,那么将其与nums[p0]进行交换,并将p0向后移动一个位置。连续的0之后是连续的1,因此如果将0
与nums[p0]进行交换的话,那么可能会把一个1交换出去。当p0<p1时,已经将一些1连续地放在头部,此时一定会把一个1交换出去,导致答案错误。
如果p0<p1,需要再将nums[i]与nums[p1]进行交换,其中i时当前遍历到的位置,在进行第一次交换后,nums[i]的值为1,需要将这个1放在头部的末端。
在最后,无论是否有p0<p1,需要将p0和p1均向后移动一个位置,而不是仅将p0向后移动一个位置。
 
屏幕截图 2025-09-30 201623

 

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();
        int p0 = 0,p1 = 0;
        for(int i=0;i<n;i++){
            if(nums[i]==1){
                swap(nums[i],nums[p1]);
                ++p1;
            }else if(nums[i]==0){
                swap(nums[i],nums[p0]);
                if(p0<p1){
                    swap(nums[i],nums[p1]);
                }
                ++p0;
                ++p1;
            }
        }
    }
};
 
力扣78题 子集
组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
子集问题是一种组合问题,因为集合是无序的,因此写回溯算法的时候,for就要从startindex开始,而不是从0开始。
1.递归函数参数
vector<vector<int>>result;
vector<int>path;
void backtracing(vector<int>&nums,int startindex){
2.递归终止条件
startindex已经大于数组的长度了,就终止了。
if(startindex>=nums.size()){
   return;
}
3.单层搜索逻辑
求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。
for(int i=startindex;i<nums.size();i++){
    path.push_back(nums[i]);
    backtracing(nums,i+1);
    path.pop_back();
}
 
整体代码:
class Solution {
public:
    vector<vector<int>>result;
    vector<int>path;
    void backtracing(vector<int>&nums,int startindex){
        result.push_back(path);
        if(startindex>=nums.size()){
            return;
        }
        for(int i=startindex;i<nums.size();i++){
            path.push_back(nums[i]);
            backtracing(nums,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        result.clear();
        path.clear();
        backtracing(nums,0);
        return result;
    }
};
 
 
力扣148题 排序链表
思想就是以下两个题目
力扣876题 链表的中间结点
力扣21题  合并两个有序链表
归并排序(分治)
1.找到链表的中间结点head2的前一个节点,并断开head2与其前一个节点的连接。就把原链表均分成了两段更短的链表,。
2.分治,递归调用sortlist,分别排序head和head2。
3.排序后,得到了两个有序链表,合并两个有序链表,得到排序后的链表,返回链表头节点。
class Solution {
public:
    //876  链表的中间结点(快慢指针)
    ListNode *middleNode(ListNode *head){
        ListNode *pre = head;
        ListNode *slow = head;
        ListNode *fast = head;
        while(fast && fast->next){
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        pre->next = nullptr;
        return slow;
    }
    //  合并两个有序链表
    ListNode *mergeTwoLists(ListNode *list1,ListNode *list2){
        ListNode dummy;
        ListNode *cur = &dummy;
        while(list1 && list2){
             if(list1->val < list2->val){
                cur->next = list1;
                list1 = list1->next;
             }else{
                cur->next = list2;
                list2 = list2->next;
             }
             cur = cur->next;
        }
        cur->next = list1 ? list1:list2;
        return dummy.next;
    }

    ListNode* sortList(ListNode* head) {
        if(head==nullptr || head->next == nullptr){
            return head;
        }
        ListNode * head2 = middleNode(head);
        head = sortList(head);
        head2 = sortList(head2);

        return mergeTwoLists(head,head2);
    }
};
 
 
力扣215题.数组中的第k个最大元素
使用编程语言的内置排序算法对数组nums进行排序,然后返回第N-k个元素即可。
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        return nums[nums.size()-k];
    }
};
 
力扣221题最大正方形
 思路和力扣72题编辑距离,还有力扣5题最长回文子串类似。
class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        int m = matrix.size(),n = matrix[0].size(),ans = 0;
        vector<vector<int>>dp(m,vector<int>(n));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(matrix[i][j] =='1'){
                    if(i==0 || j==0){
                        dp[i][j] = 1;
                    }else{
                        dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
                       
                    }
                    ans = max(ans,dp[i][j]);
                }
            }
        }
        return ans * ans;
    }
};
 
 
 
力扣287题 寻找重复数
 使用哈希表法记录数组的各个数字,当查找重复数字则直接返回。
1.初始化:新建HashSet,记为hmap。
2.遍历数组nums中的每个数字num:
(1)当num在hmap中,说明重复,直接返回num。
(2)将num添加至hmap中。
3.返回-1。本题中一定有重复数字,因此这里返回多少都可以。
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        unordered_map<int,bool>map;
        for(int num:nums){
            if(map[num]) return num;
            map[num] = true;
        }
        return -1;
    }
};
 
 
 
 
力扣 437题.路径总和III
思想和112题,113题很类似
思路:
1.先序递归 遍历每个节点
2.以每个节点作为起始节点DFS寻找满足条件的路径
先调用dfs函数从root开始查找路径,再调用pathsum函数到root左右子树开始查找。
class Solution {
public:
    int rootSum(TreeNode *root,long long targetSum){
        if(root==nullptr){
            return 0;
        }
        int ret = 0;
        if(root->val==targetSum){
            ret++;
        }
        ret += rootSum(root->left,targetSum-root->val);
        ret += rootSum(root->right,targetSum-root->val);
        return ret;
    }
    int pathSum(TreeNode* root, int targetSum) {
        if(root==nullptr){
            return 0;
        }
        int ret = rootSum(root,(long long)targetSum);
        ret += pathSum(root->left,targetSum);
        ret += pathSum(root->right,targetSum);
        return ret;
    }
};
 
 
 
 
 
http://www.hskmm.com/?act=detail&tid=22286

相关文章:

  • 笔记本电脑重装系统后找不到5G WIFI无线网或蓝牙模块消失的解决方案
  • 菜鸟坚持记录-开头篇
  • AI+传统工作流:Photoshop/Excel的智能插件开发指南 - 实践
  • Typora 笔记迁移 Obsidian 图片附件库批量移动方法,适用于笔记整理。
  • 2025年确有专长培训权威推荐榜:专业资质与特色诊疗口碑之选
  • 开源 C# 快速构建(五)自定义控件--仪表盘
  • 2025中医师承培训、考试、认证机构权威推荐榜:名师传承与临床实践口碑之选
  • 电子文件分类整理与双向同步 2025年10月1日
  • C++版搜索与图论算法 - 详解
  • 62. 不同路径
  • 达成设计卓越:全面解析 IC 设计中的验证之道
  • Typora 笔记迁移 Obsidian 图片链接转换
  • Java 运行 Word 文档标签并赋值:从基础到实战
  • 词云组件
  • 2025 年超声波清洗机品牌最新权威推荐排行榜:龙门式 / 悬挂式 / 全自动等多类型设备厂家 TOP3 精选,助力企业精准选购
  • 树的统一迭代法
  • 2025 年冷却塔品牌最新推荐排行榜:玻璃钢冷却塔、闭式冷却塔、方型逆流式冷却塔优质厂家 TOP3 精选,赋能企业选购
  • DailyPaper-2025-9-30
  • Powershell 管理 后台/计划 作业(六)
  • 32. 最长有效括号
  • java17及以上版本如何抵御TemplatesImpl注入
  • 详细介绍:【C++实战(53)】C++11线程库:开启多线程编程新世界
  • 将图片某个区域批量填充白色(jsx代码)
  • 《初等数论(第四版,北京大学出版社,潘承洞,潘承彪著)》阅读笔记+心得
  • 完整教程:Word和WPS文字中的自动编号和文字间距过大怎么办?
  • markdown笔记文件批量打上时间戳
  • 251001
  • 微服务调整中心高可用设计:从踩坑到落地的实战指南(二)
  • NOIP2025模拟赛27
  • NOIP2025模拟赛28