各类型算法题整理(python、c++版)hot100

news2024/9/9 1:14:48

1. 组合数:n个数找k个数的组合

这题的核心是每次遍历从begin到n之间的所有数,并放到一个path里。当path=k的时候返回。要注意两点:

(1)不要在path长度为k的时候清空path!回溯不需要清空,因为回溯的时候就已经pop了

(2)python不能直接results.append(path),因为path在回溯过程中一直在变化!append里只是加了它的引用,应该用copy()

n = 10
k = 2
results = []
path = []
def findk(begin):
    if len(path) == k:
        results.append(path.copy())
        return
    for i in range(begin, n+1):
        path.append(i)
        findk(i+1)
        path.pop()

findk(1)
print(results)

剪枝优化方式:因为path小于k的根本就不会当成结果,所以n-begin<k的时候,begin就不用再递归了。改成:

for(int i = begin; i<=n-(k-path.size())+1;i++){

2. 无重复字符的最长子串

双指针问题,我想了好久,这题边界好容易出错。双指针要注意的是,左右指针相等的时候应该意味着当前子数组的长度为1.所以初始化最好置左指针为0,右指针为-1,每次先尝试右指针+1.

    def lengthOfLongestSubstring(self, s: str) -> int:
        i = 0
        j = -1
        res = 0
        tmpset = set()
        for i in range(len(s)):
            while j+1 < len(s) and s[j+1] not in tmpset:
                tmpset.add(s[j+1])
                j = j+1
            res = max(res, len(tmpset))
            print(tmpset)
            print(i," ",j)
            tmpset.remove(s[i])
        return res

3.  全排列问题(hot100)

要注意的点:(1)def findk需要定义成局部函数,不然在permute里无法调用。(2)全排列的区别是,不要设置begin,因为21和12是不一样的,只需要判断是否重复。

    def permute(self, nums: List[int]) -> List[List[int]]:
        path = []
        results = []
        def findk(nums):
            if len(path) == len(nums):
                results.append(path.copy())
                return
            for i in range(len(nums)):
                if nums[i] in path:
                    continue
                path.append(nums[i])
                findk(nums)
                path.remove(nums[i])
        findk(nums)
        return results

4. 删除有序数组的重复项

看到子串这种一定要想到双指针啊!!!想到了就会很简单。只用一个数组,一次循环就能解决,slow记录,fast遍历

        slow = 0
        for fast in range(len(nums)):
            if nums[fast] != nums[slow]:
                nums[slow+1] = nums[fast]
                slow=slow+1
        return slow+1

5. 子集(hot100)

回溯问题,还是三部曲,主要就是要搞清楚什么时候res append到里面,然后限制条件是path不重复

    def subsets(self, nums: List[int]) -> List[List[int]]:
        path = []
        res = []
        def findk(begin):
            res.append(path.copy())
            if begin > len(nums)-1:
                return
            for i in range(begin,len(nums)):
                if nums[i] not in path:
                    path.append(nums[i])
                    findk(i)
                    path.remove(nums[i])

        findk(0)
        return res

6. 环形链表:找到入环后的第一个节点

主要解决方法有两种,1是哈希表,直接把node插入到哈希表里就行了

2 是快慢指针,难点是如何判断入环的地方?

        ListNode * slow = head, *fast = head, * newl = head;
        if (head == nullptr) return nullptr;
        while(fast->next!=nullptr && fast->next->next != nullptr){
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast){
                while(newl != slow){
                    newl = newl->next;
                    slow = slow->next;
                }
                return newl;
            }
        }
        return nullptr;
    }

7. 电话号码的字符串

回溯的常规思路,就是要注意他这里path不能作为全局变量传到局部函数里面。要当成参数传进去。(应该是因为path是一个str,如果是list就可以传进去)

    def letterCombinations(self, digits: str) -> List[str]:
        mp = {}
        mp['2'] = "abc"
        mp['3'] = "def"
        mp['4'] = "ghi"
        mp['5'] = "jkl"
        mp['6'] = "mno"
        mp['7'] = "pqrs"
        mp['8'] = "tuv"
        mp['9'] = "wxyz"
        results = []
        def findk(idx,path):
            if idx == len(digits):
                results.append(path)
                return
            num = digits[idx]
            for i in mp[num]:
                path = path+i
                findk(idx+1,path)
                path = path[:-1]
        if len(digits) ==0:
            return results
        findk(0,"")
        return results

8. 岛屿数量

就说python和c++一起写!!!一直有个bug最后才发现是因为c++for后面忘了加大括号!!一定不能犯这种低级错误!

注意:每次写算法都要先判断一下输入数据的长度为0时输出应该怎么办

还有:vector二维矩阵的初始化要记住:

vector<vector<bool>> visited= vector<vector<bool>>(n, vector<bool>(m,false));
class Solution {
public:
    int gotox[4] = {1,-1,0,0};
    int gotoy[4] = {0,0,1,-1};

    void dfs(vector<vector<char>>& grid,vector<vector<bool>>& visited,int x,int y){
        int n = grid.size(), m = grid[0].size();

        for(int t =0;t<4;t++){
            int nextx = x + gotox[t];
            int nexty = y + gotoy[t];
            if(nextx >= 0 && nextx < n && nexty >=0 && nexty <m){
                if(visited[nextx][nexty]==false && grid[nextx][nexty] == '1'){
                    visited[nextx][nexty] = true;
                    dfs(grid,visited, nextx,nexty);
                }

            }
        }
    }
    int numIslands(vector<vector<char>>& grid) {
        int res = 0;
        int n = grid.size();
        int m = grid[0].size();
       vector<vector<bool>> visited= vector<vector<bool>>(n, vector<bool>(m,false));
        for(int i =0;i<n;i++){
            for(int j =0;j<m;j++){
                if(visited[i][j] == false && grid[i][j] == '1'){
                
                    res++;
                    dfs(grid,visited,i,j);
                    
                }
            }
        }
        return res;
    }
};

9. 括号生成(回溯)

主要难点在于判断括号是否有效,就是要注意记录左括号和右括号的数量,保证左括号数量大于右括号数量时才往里面加入右括号。

   int lenleft = 0, lenright = 0;
    string path = "";
    vector<string> res;
    void findk(int n){
        if (lenleft+lenright>=2*n){
            res.push_back(path);
            return;
        }
        if(lenleft < n){
            lenleft++;
            path.push_back('(');
            findk(n);
            path.pop_back();
            lenleft--;
        }
        if(lenright < n && lenright<lenleft){
            lenright++;
            path.push_back(')');
            findk(n);
            path.pop_back();
            lenright--;
        }
    }
    vector<string> generateParenthesis(int n) {
        findk(n);
        return res;
    }

10. 单词搜索(麻烦,需要二刷)

先用了dfs+回溯的方法,但是一直超时:

public:
    int indx[4] = {0,0,1,-1}, indy[4] = {1,-1,0,0};
    bool visited[10][10] = {false};

    bool findk(int x,int y,int index,string word,vector<vector<char>>& board){
        if (index == word.size()){
            return true;
        }
        bool res = false;
        for(int i=0;i<4;i++){
            int nextx = x + indx[i];
            int nexty = y + indy[i];
             
            if (nextx >= board.size() || nextx < 0 || nexty >= board[0].size()||nexty <0 ) continue;
            // cout<<nextx<<nexty<<endl;
            if (board[nextx][nexty] == word[index] && !visited[nextx][nexty]){
                visited[nextx][nexty] = true;
                cout<<nextx<<nexty<<endl;
                res = res || findk(nextx,nexty,index+1,word,board);
                visited[nextx][nexty] = false;
            }
        }
        return res;
    }    
    bool exist(vector<vector<char>>& board, string word) {

        for(int i = 0;i<board.size();i++){
            for(int j =0;j<board[0].size();j++){
                if(board[i][j] == word[0] && !visited[i][j]){
                    visited[i][j] = true;
                    if (findk(i,j,1,word,board)) return true;
                    visited[i][j] = false;
                }
            }
        }
        return false;
    }

改成思路:不要把判断放在for循环里面,而是放在一开始进入dfs的地方,就判断xy是否符合规则

    int indx[4] = {0,0,1,-1}, indy[4] = {1,-1,0,0};
    bool visited[10][10] = {false};

    bool findk(int x,int y,int index,string word,vector<vector<char>>& board){
        if (index == word.size()){
            return true;
        }
        if (x >= board.size() || x < 0 || y >= board[0].size()||y <0 ) return false;
        if (board[x][y] != word[index] || visited[x][y] == true ) return false;
        visited[x][y] = true;
        bool res = false;
        for(int i=0;i<4;i++){
            int nextx = x + indx[i];
            int nexty = y + indy[i];
            res = res || findk(nextx,nexty,index+1,word,board);
        }
        
        visited[x][y] = false;
        return res;
    }    
    bool exist(vector<vector<char>>& board, string word) {

        for(int i = 0;i<board.size();i++){
            for(int j =0;j<board[0].size();j++){
                if(board[i][j] == word[0] && findk(i,j,0,word,board)){
                    return true;
                }
            }
        }
        return false;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1959031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

夏季如何预防脑血管疾病

众所周知&#xff0c;冬季是脑血管病的高发季节。然而&#xff0c;还有资料显示&#xff0c;在炎炎夏日&#xff0c;脑血管疾病的发病率也呈明显的上升趋势。为什么夏季也会高发脑血管病呢&#xff1f;我们来一起了解一下。 1. 出汗量大大增加&#xff0c;血容量就会减少&#…

【Java】韩顺平Java学习笔记 第22章 多用户通讯系统

文章目录 项目开发流程需求分析整体分析用户登录注意 拉取在线用户列表无异常退出私聊功能注意 发送文件服务端推送新闻接收离线消息和文件 项目开发流程 需求分析设计阶段实现阶段测试阶段实施阶段维护阶段 需求分析 用户登录拉取在线用户列表无异常退出&#xff08;客户端、…

【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 引导程序(boot loader)--(十)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

【C++】嵌套循环案例 乘法口诀表

乘法口诀表利用嵌套循环语句就可以实现 下面是一个实例 #include<iostream> using namespace std;int main() {for (int i 1; i < 10; i){for (int j 1; j < i; j){cout << j << " * " << i << " " << i *…

Agent终于能主动进化?揭秘首个让AI自我进化的训练框架!突破人类专家局限,告别手动调优!端到端符号化框架如何引领AI自我革命

随着大型语言模型(LLMs)的兴起和AI Agent框架的开源&#xff0c;基于这些强大模型的智能体在学术界和工业界受到了极大的关注&#xff0c;并在多个场景中取得了显著的成果。然而&#xff0c;尽管AI Agent在一些应用中已经落地&#xff0c;其研究和开发仍然主要依赖于“专家中心…

Apollo:目录分析, test ok

apollo: Apollo (阿波罗)是一个开放的、完整的、安全的平台,将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统,快速搭建一套属于自己的自动驾驶系统。 - Gitee.comhttps://github.com/ApolloAuto/apolloapollo 目录名称目录作用cyber消息中间件,替换ros作为消息层…

2024年【制冷与空调设备运行操作】考试题及制冷与空调设备运行操作新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备运行操作考试题根据新制冷与空调设备运行操作考试大纲要求&#xff0c;安全生产模拟考试一点通将制冷与空调设备运行操作模拟考试试题进行汇编&#xff0c;组成一套制冷与空调设备运行操作全真模拟考试…

python绘制图像无法显示汉字、数字

解决的问题&#xff1a;python绘制图像无法正确显示汉字、数字&#xff0c;图中汉字数字以方块形式显示。 直接先上代码&#xff1a; # 确保图表中的汉字可以显示 plt.rcParams["font.sans-serif"] ["SimHei"] plt.rcParams["axes.unicode_minus…

25.惰性队列

介绍 消费者由于各种原因而致使长时间不能消费消息造成堆积。比如有一百万条消息发送到mq中&#xff0c;消费者这时宕机了不能消费消息&#xff0c;造成了消息堆积。惰性队列就有必要了。 正常情况下&#xff0c;消息保存在内存中。消费者从内存中读取消息消费&#xff0c;速…

【设计模式】代理模式详解

1.简介 代理模式是常用的Java设计模式&#xff0c;该模式的特点是代理类与委托类共享相同的接口。代理类主要负责预处理消息、过滤消息、将消息转发给委托类&#xff0c;并在事后处理消息等。代理类与委托类之间通常存在关联关系&#xff0c;一个代理类对象与一个委托类对象关…

TPM管理咨询公司在项目实施过程中提供哪些培训和支持?

在竞争激烈的市场环境中&#xff0c;企业项目的成功实施不仅是技术的较量&#xff0c;更是管理智慧的体现。而TPM管理咨询公司&#xff0c;作为提升企业运营效率与竞争力的专业伙伴&#xff0c;深知在项目推进的每一步中&#xff0c;专业的培训与强大的支持体系对于确保项目顺利…

shell脚本编写、一键安装nginx、条件语句、 检测网段脚本、 打印九九乘法表、

1.shell脚本 1.编写及运行脚本 [root13git ~]# vim hello.sh [root13git ~]# bash hello.sh [root13git ~]# sh hello.sh [root13git ~]# source hello.sh //在当前进程执行 [root13git ~]# chmod x hello.sh [root13git ~]# ./hello.sh 2.一键安装nginx [root13g…

小红书笔记评论采集全攻略:三种高效方法教你批量导出

摘要&#xff1a; 本文将深入探讨如何利用Python高效采集小红书平台上的笔记评论&#xff0c;通过三种实战策略&#xff0c;手把手教你实现批量数据导出。无论是市场分析、竞品监测还是用户反馈收集&#xff0c;这些技巧都将为你解锁新效率。 一、引言&#xff1a;小红书数据…

芋道源码/yudao-cloud二次开发日记(商品sku数据归类为规格属性)

商品的每一条规格和属性在数据库里都是单一的一条数据&#xff0c;从数据库里查出来后&#xff0c;该怎么归类为对应的规格和属性值&#xff1f;如下图&#xff1a; 在商城模块&#xff0c;商品的单规格、多规格、单属性、多属性功能可以说是非常完整&#xff0c;如下图&#x…

Github2024-07-29 开源项目周报Top15

根据Github Trendings的统计,本周(2024-07-29统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目2Java项目2HTML项目2C项目2TypeScript项目2JavaScript项目2非开发语言项目1Vue项目1Go项目1Dart项目1C++项目1Rust项目1Jupyter Note…

项目计划书编制方案(DOC)

项目开发计划包括项目描述、项目组织、成本预算、人力资源估算、设备资源计划、沟通计划、采购计划、风险计划、项目过程定义及项目的进度安排和里程碑、质量计划、数据管理计划、度量和分析计划、监控计划和培训计划等。 软件资料清单列表部分文档&#xff1a; 工作安排任务书…

Temporal(时效)模式01

Andy Carlson, Sharon Estepp, Martin Fowler 著&#xff0c;透明 译 抽象 在面向对象设计中&#xff0c;我们不断使用“对象”&#xff08;object&#xff09;这个词。对象不仅仅用来表现真实世界中存在的物件&#xff0c;它们也被用来表现那些曾经存在但已经消失了的物件&…

关于Docker Engine AuthZ 插件授权绕过漏洞 (CVE-2024-41110)

一、漏洞概述 漏洞名称&#xff1a;Docker Engine AuthZ 插件授权绕过漏洞 &#xff08;CVE-2024-41110&#xff09; 漏洞等级&#xff1a;高危 漏洞描述&#xff1a;DockerEngine是Docker的核心组件&#xff0c;是一 个开源的容器引擎&#xff0c;负责构建、运行和管理容器…

又一新AI搜索工具,OpenAI 推出新的搜索方式 SearchGPT

系列文章目录 每天推荐AI工具系列文章回顾&#xff1a; 选择 haiyi海艺图像生成、LoRA、模型的使用和训练网站 tusiart吐司艺术图像生成、LoRA 模型的使用和训练网站 解锁AI创造力的无限可能&#xff1a;探索Vivago.ai的革命性功能 文章目录 系列文章目录前言一、SearchGPT…

html+css+js前端作业和平精英6个页面页面带js

htmlcssjs前端作业和平精英6个页面页面带js 下载地址 https://download.csdn.net/download/qq_42431718/89595600 目录1 目录2 项目视频 htmlcssjs前端作业和平精英6个页面带js 页面1 页面2 页面3 页面4 页面5 页面6