/秋招突击——7/21——复习{堆——数组中的第K大元素}——新作{回溯——全排列、子集、电话号码的字母组合、组合总和、括号生成}
文章目录
- 引言
- 复习
- 数组中的第K大的最大元素
- 复习实现
- 参考实现
- 新作
- 回溯模板
- 46 全排列
- 个人实现
- 参考实现
- 子集
- 个人实现
- 参考实现
- 电话号码的字母组合
- 复习实现
- 组合总和
- 个人实现
- 参考实现
- 括号生成
- 复习实现
- 总结
引言
- 昨天的科大讯飞笔试做的稀烂,今天回来好好练习一下,主要是针对下述两种题型,分别是对顶堆还有回溯,对顶堆的题目并不多,主要是回溯。下次再遇到这种题目,直接背模板,然后开始做!
复习
数组中的第K大的最大元素
-
题目链接
-
第一次做
-
第二次做
-
不知不觉已经是第三次做了,感觉还是有点懵,O(N)的时间复杂度,说明可以遍历多次,但是不能嵌套遍历!想想看哈
复习实现
- 我还是会使用堆实现,并且发现了如果第一次不会做,那么后续会一直不会做,记不住!这里还是要总结.
- 这里还是使用了堆排序时间,虽然时间复杂度不满足要求,但是单纯为了练习一下!
class Solution {public int findKthLargest(int[] nums, int k) {//define m is lenght ,and pq to sort the numint m = nums.length;Queue<Integer> pq = new PriorityQueue<>();// traverse the numsfor(int i = 0;i < m;i ++){if(pq.size() < k) pq.add(nums[i]);else{if(nums[i] > pq.peek()){pq.poll();pq.add(nums[i]);}}}return pq.peek();}
}

参考实现
- 这里正确的做法是使用快排进行修改,这里先回顾一下快排的模板
void quickSort(nums q,int l ,int r){if(l >= r) return;int i = l - 1,j = r + 1,x = q[(l + r)>>1];while(i< j){do i ++ ;while(q[i] < x);do j ++ ;while(q[j] > x);if(i < j) swap(q[i],q[j]);}quickSort(q,l,j),quickSort(q,j + 1,r);
}
- 这样背!虽然很蹩脚,但是能记住就行了,记住了就好些了!
- 左右相交就返回
- 左左右右是 ij
- i加小 j减大
- i小j大做交换
- j做划分两边排
这里是要求第K大的数字,所以得改变一下i和j交换的方向,最后的序列应该是从大到小,然后再是找第k大的元素,这道题是记住了!修改的话,就从最后的终止条件开始!
具体实现
class Solution {public int quickSort(int[] nums,int l ,int r,int k){if(l == r) return nums[k];int i = l - 1,j = r + 1,x = nums[(l + r) >> 1];while(i < j){do i ++;while(nums[i] > x);do j --;while(nums[j] < x);if(i < j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}}if(j >= k) return quickSort(nums,l,j,k);else return quickSort(nums,j + 1,r,k);}public int findKthLargest(int[] nums, int k) {//define m is lenght ,and pq to sort the numint m = nums.length;// traverse the numsint x = quickSort(nums,0,m - 1,k - 1 );return x;}
}

新作
回溯模板
void dfs(int[] nums,int idx){// 终止条件if(idx == termination){// 目标操作return;}//迭代内容for(){dfs(nums,idx + 1);// 恢复现场}
}
-
这里要确定两个东西,一个是总的迭代对象,还有一个是单次迭代的修改内容,下面把下面几个题按照这个模板都分析一下!
-
全排列
- n个对象排在n个位置,每一个位置都要迭代一次,然后每一次都要从剩下没有排的对象中选出来的,所以
- 总的迭代次数:n个位置,终止条件就是迭代n次
- 单次迭代内容:在可选的选项中随机选择一个。
- n个对象排在n个位置,每一个位置都要迭代一次,然后每一次都要从剩下没有排的对象中选出来的,所以
-
子集
- n个对象,其中选择任意一个有几种选择方法,遍历每一个元素,然后根据每一个元素决定是否选中,所以
- 总的迭代次数:n个对象,终止条件所有元素都决策过了。
- 单次迭代内容:当前元素是否选中两种情况,选中当前元素,不选中当前元素,
- n个对象,其中选择任意一个有几种选择方法,遍历每一个元素,然后根据每一个元素决定是否选中,所以
-
组合总和
- n个对象,选择其中若干个若干次,形成目标值,所以
- 总的迭代次数:n个元素,每一个元素都要遍历
- 单次迭代内容:当前元素选择零次,或者若干次
- n个对象,选择其中若干个若干次,形成目标值,所以
其实如果能够从树的角度分析,效果会更好,树的深度就是总的迭代次数,单个节点的子节点数也就是树的宽度,就是单次迭代需要考虑的内容
46 全排列
- 题目链接

注意 - 所有整数互不相同,不用处理特殊情况。
- 数组的长度会出现的一的情况,边界情况,需要特殊处理!
个人实现
- 标准回溯,确定一个模板直接开始写。
- 终止条件:idx = 0,并将结果加入到res中
- 迭代条件:遍历剩余的元素,随机加入到临时列表中
class Solution {public List<List<Integer>> res = new ArrayList<>();void dfs(int[] nums,int idx,List<Integer> list,Set<Integer> set){if(idx == 0){res.add(new ArrayList(list));return;}// iterator conditionfor(int i = 0;i < nums.length;i ++){int x = nums[i];if(!set.contains(x)){list.add(x);set.add(x);dfs(nums,idx - 1,list,set);list.remove(list.size() - 1);set.remove(x);}}}public List<List<Integer>> permute(int[] nums) {List<Integer> list = new ArrayList<>();Set<Integer> set = new HashSet<>();dfs(nums,nums.length,list,set);return res;}
}
觉得写的有点繁琐,看看参考的教程是怎么写的
- 注意,在Java中res.add方法是引用传递,需要创建一个同元素变量的副本才行,不然会越界!
参考实现
-
明确需要记录的状态
- 每一个位置具体的位置保存的数字,也就是list
- 每一个数字的使用情况,使用set
- 递归到了第几步
-
他是使用全局变量来声明,没有使用形参传递对应
这里就不写了,基本上都是一致的
子集
- 题目链接

注意 - 存在数组为1的特殊情况,可能需要特殊处理
- 各个元素互不相同
- 元素有负数的情况
个人实现
- 刚才那道题目是所有的排列情况,这道题目是所有的组合情况,应该也可以使用回溯实现。这个和刚才相同,不过是在每一次的改变环境的时候,就将结果进行保存!
class Solution {List<Integer> list = new ArrayList<>();Set<Integer> set = new HashSet<>();Set<List<Integer>> res = new HashSet<>();void dfs(int[] nums,int idx){if(idx == nums.length){List<Integer> temp = new ArrayList<>(list);Collections.sort(temp);res.add(temp);}for(int i = 0;i < nums.length;i ++){int x = nums[i];if(!set.contains(x)){set.add(x);list.add(x);List<Integer> temp = new ArrayList<>(list);Collections.sort(temp);res.add(temp);dfs(nums,idx + 1);set.remove(x);list.remove(list.size() - 1);}}}public List<List<Integer>> subsets(int[] nums) {res.add(Arrays.asList());dfs(nums,0);List<List<Integer>> resList = new ArrayList<>();for(List<Integer> x:res){resList.add(x);}return resList;}
}

上面这样做就不对,得再想想,如果是回溯的话,得更新一下状态的改变,不能直愣愣的添加对应的元素!出来结果了,然后再添加!
- 好蠢呀,没想到,没想到,既然没想到,记下来,下次肯定能够想到!
参考实现
方法一、DFS
递归的条件
- 每一个元素只有两种情况,放或者不放,所以遍历这两种情况就行了!
class Solution {List<Integer> list = new ArrayList<>();List<List<Integer>> res = new ArrayList<>();void dfs(int[] nums,int idx){// termiante conditionif(idx == nums.length){res.add(new ArrayList(list));return ;}// traverse all the condition// get the idx numlist.add(nums[idx]);dfs(nums,idx + 1);list.remove(list.size() - 1);// do not get the idx numdfs(nums,idx + 1);}public List<List<Integer>> subsets(int[] nums) {dfs(nums,0);return res;}
}

方法二、位运算
- 将这个问题转化为对应的二进制表示,每一个物体只有放或者不放两种情况,对应就是不同的二进制数,而且全排列的最终结果数量就是 2 n 2^n 2n
具体实现如下
这里刚好练习一下Java中的二进制数是怎么操作的!
class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res = new ArrayList<>();int n = nums.length;// traverse all the binary numfor(int i = 0;i < (1 << n);i ++){List<Integer> temp = new ArrayList<>();for(int j = 0;j < n;j ++){// judge the j is 0 or 1if(((i >> j) & 1) == 1){temp.add(nums[j]);}}res.add(temp);}return res;}
}
电话号码的字母组合
- 题目链接
- 第一次做
复习实现
class Solution {Map<Character,List<Character>> map = new HashMap<>();StringBuilder str = new StringBuilder();List<String> res = new ArrayList<>();void dfs(String digits,int idx){if(idx == digits.length()){//System.out.println(str.toString());res.add(str.toString());return;}for(char x:map.get(digits.charAt(idx))){str.append(x);dfs(digits,idx + 1);str.deleteCharAt(str.length() - 1);}}public List<String> letterCombinations(String d) {map.put('2',Arrays.asList('a','b','c'));map.put('3',Arrays.asList('d','e','f'));map.put('4',Arrays.asList('g','h','i'));map.put('5',Arrays.asList('j','k','l'));map.put('6',Arrays.asList('m','n','o'));map.put('7',Arrays.asList('p','q','r','s'));map.put('8',Arrays.asList('t','u','v'));map.put('9',Arrays.asList('w','x','y','z')); if(d.length() == 0) return res;dfs(d,0);return res;}
}

- 没以前使用C++实现起来那么快,写起来也没有那么方便!
组合总和
- 题目链接

注意 - 所有元素互不相同
- 每一个元素可以放很多次
个人实现
- 这题可以使用两种方式实现
- 完全背包问题,不过需要记录对应的背包状态,时间复杂度比较低,但是不知道怎么记录满足条件的状态
- 随便选一个,装满为止;F-V,加上价值,这里价值为零
- 暴力回溯,时间复杂度高
- 完全背包问题,不过需要记录对应的背包状态,时间复杂度比较低,但是不知道怎么记录满足条件的状态
暴力回溯
class Solution {List<Integer> list = new ArrayList<>();List<List<Integer>> resList = new ArrayList<>();Set<List<Integer>> res = new HashSet<>();// brute dfs to solve the problemvoid dfs(int[] candi,int tar,int temp){if(temp == tar){List<Integer> tempList = new ArrayList(list);Collections.sort(tempList);res.add(tempList);return;}for(int i = 0;i < candi.length;i ++){if(temp + candi[i] <= tar){// put//System.out.println(candi[i]);list.add(candi[i]);dfs(candi,tar,temp + candi[i]);list.remove(list.size() - 1);}}}public List<List<Integer>> combinationSum(int[] candidates, int target) {dfs(candidates,target,0);for(List<Integer> x:res){resList.add(x);}return resList;}
}

我靠,这个居然能过,也是离谱了!
完全背包问题
class Solution {List<Integer> list = new ArrayList<>();List<List<Integer>> resList = new ArrayList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {int[] f = new int[target + 1];f[0] = 1;for(int i = 0;i < candidates;i ++){for(int j = candidates[i];j < target;j ++){f[j] = f[j] + f[j - candidates[i]];}}return f[target - 1];}
}
- 这里只能写成这样,因为我并不知道怎么保存中间状态!
不能用完全背包,完全背包并不能获取中间状态!!
参考实现
- 只能说我对于的回溯的理解还是不够深刻,两种存放方式
- 是否放当前的数字,要用深度u控制,防止出现死循环
- 当前物体一定要放,但是顺序不同,需要set控制是否出现
class Solution {List<Integer> list = new ArrayList<>();List<List<Integer>> resList = new ArrayList<>();void dfs(int[] candidates,int dpt,int tar){if(tar == 0){resList.add(new ArrayList(list));return;}if(dpt == candidates.length) return;for(int i = 0;i * candidates[dpt] <= tar ;i ++){dfs(candidates,dpt + 1,tar - i * candidates[dpt]);list.add(candidates[dpt]);} for(int i = 0; i * candidates[dpt] <= tar ;i ++)list.remove(list.size() - 1);}public List<List<Integer>> combinationSum(int[] candidates, int target) {dfs(candidates,0,target);return resList;}
}

实现起来确实更优!如果放或者不放,还是需要使用的深度进行控制!
无论怎么样,都需要加上的对应idx控制
括号生成
- 题目链接
- 第一次学习链接
复习实现
class Solution {// define the structure to store the resultList<String> res = new ArrayList<>();StringBuilder str = new StringBuilder();void dfs(int idx,int n,int l,int r){if(idx == 2 * n && l == r){if(l == r)res.add(str.toString());return ;}// remove the special situationif(r > l || l > n || r > n) return;str.append('(');dfs(idx + 1,n,l + 1,r);str.deleteCharAt(str.length() - 1);str.append(')');dfs(idx + 1,n,l ,r + 1);str.deleteCharAt(str.length() - 1);}public List<String> generateParenthesis(int n) {dfs(0,n,0,0);return res;}
}

上一次写的真丝滑!
vector<string> res;
void dfs(int n,int lc,int rc,string s){/** n表示括号数量,lc表示左括号数量,rc表示右括号数量,s表示字符串*/// 判定什么时候加左括号if (lc == n && rc == n) res.push_back(s); else{// 什么时候加右括号if (lc < n) dfs(n,lc + 1,rc,s + "(");if (lc > rc && rc < n) dfs(n,lc,rc + 1,s + ")");}
}vector<string> generateParenthesis(int n){dfs(n,0,0,"");return res;
}
总结
- 今天这几道题做完了,算是对于深度有了更加深刻的认识!最好能够画出对应的树形结构,树的高度就是总的迭代次数,树的宽度就是单次迭代需要迭代的内容!
- 写回溯,还是比写其他算法要轻松很多!
- 写回溯,一定要画图!写算法一定要画图,转成对应的数据结构!回溯就是可以转成对应的树形结构!
- 一定要要记得恢复现场,每一步都要恢复现场,因为你的编程习惯是共用一个StringBuilder。
相关文章:
/秋招突击——7/21——复习{堆——数组中的第K大元素}——新作{回溯——全排列、子集、电话号码的字母组合、组合总和、括号生成}
文章目录 引言复习数组中的第K大的最大元素复习实现参考实现 新作回溯模板46 全排列个人实现参考实现 子集个人实现参考实现 电话号码的字母组合复习实现 组合总和个人实现参考实现 括号生成复习实现 总结 引言 昨天的科大讯飞笔试做的稀烂,今天回来好好练习一下&a…...
matlab 异常值检测与处理——Robust Z-score法
目录 一、算法原理1、概述2、主要函数3、参考文献二、代码实现三、结果展示四、相关链接本文由CSDN点云侠翻译,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、概述 Robust Z-score法也被称为中位数绝对偏差法。它类似于Z-sc…...
Ubuntu 20安装JDK17和MySQL8.0
一.jdk 安装JDK 第一步:更新软件包:sudo apt update 第二步:安装JDK:sudo apt install openjdk-17-jdk 第三步:检测JDK: java -version 卸载JDK: 第一步:移除JDK包:apt-get purg…...
DC-1靶场打靶第一次!!!!冲冲冲!
今天打了一下DC-1这个靶场,感觉收获比大,我就来记录一下。 我的思路是下面的这个 我们先把靶机导入,然后与我们的liunx(攻击机)在同一个网段中,这也大大的减低难度。 然后我们先对自己这个网段内存活的主机进行操作,我…...
【LeetCode】填充每个节点的下一个右侧节点指针 II
目录 一、题目二、解法完整代码 一、题目 给定一个二叉树: struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NUL…...
mac无法清空废纸篓怎么办 mac废纸篓清空了如何找回 cleanmymac误删文件怎么恢复
废纸篓相当于“一颗后悔药”,用于临时存储用户删除的文件。我们从从Mac上删除的文件,一般会进入废纸篓中。如果我们后悔了,可以从废纸篓中找回来。然而,有时我们会发现mac无法清空废纸篓,这是怎么回事?本文将探讨一些…...
树上启发加点分治思想
题目链接 思路: 对于一条链可以组成回文串,意味着最多只有一个奇数字母,比起我们记录路径各个字母的个数和,我们可以发现回文串实际上不在意真正的个数,只在意个数的奇偶。又我们发现字母只有20来个,可以使…...
【iOS】类对象的结构分析
目录 对象的分类object_getClass和class方法isa流程和继承链分析isa流程实例验证类的继承链实例验证 类的结构cache_t结构bits分析实例验证属性properties方法methods协议protocolsro类方法 类结构流程图解 对象的分类 OC中的对象主要可以分为3种:实例对象…...
接口性能优化思路
前言 日常开发中设计接口,响应时间是衡量一个接口质量的重要指标。 接口响应时间这里粗糙地分为三种: 即时响应:毫秒级,小于500毫秒快速响应:秒级,大于500毫秒且小于2秒长时间操作:大于2秒&a…...
PyQt5 多线程编程详细教程
PyQt5 多线程编程详细教程 在 PyQt5 中,多线程编程是提高应用程序性能和响应性的重要手段。本教程将详细介绍如何在 PyQt5 中使用 QThread 进行多线程编程,学习如何避免界面冻结和线程安全问题,并通过丰富的案例来展示如何实现这些功能。 Q…...
uniapp小程序上传pdf文件
<template><view class"mainInnBox"><view class"formBox"><!-- 注意,如果需要兼容微信小程序,最好通过setRules方法设置rules规则 --><u-form :model"form" ref"uForm" :rules&quo…...
Python酷库之旅-第三方库Pandas(036)
目录 一、用法精讲 111、pandas.Series.item方法 111-1、语法 111-2、参数 111-3、功能 111-4、返回值 111-5、说明 111-6、用法 111-6-1、数据准备 111-6-2、代码示例 111-6-3、结果输出 112、pandas.Series.xs方法 112-1、语法 112-2、参数 112-3、功能 112-…...
Python爬虫(2) --爬取网页页面
文章目录 爬虫URL发送请求UA伪装requests 获取想要的数据打开网页 总结完整代码 爬虫 Python 爬虫是一种自动化工具,用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持(如 requests、BeautifulSoup、Scrapy 等…...
【iOS】——探究isKindOfClass和isMemberOfClass底层实现
isKindOfClass 判断该对象是否为传入的类或其子类的实例 // 类方法实现,用于检查一个类是否属于另一个类或其父类链上的任何类。(BOOL)isKindOfClass:(Class)cls {// 从当前类开始,tcls将沿着元类的继承链向上遍历。for (Class tcls self->ISA(); …...
Python 热门面试题(七)
Python中如何拷贝对象?浅拷贝和深拷贝的区别是什么? 在Python中,拷贝对象是一个常见的需求,尤其是当你需要修改一个对象但又不想影响原始对象时。Python提供了几种拷贝对象的方法,其中最重要的是浅拷贝(sh…...
STM32项目分享:智能宠物喂食系统
目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片: 哔哩哔哩视频链接: https://www.bilibili.com/video/BV1zy411z7…...
数据结构——栈的实现(java实现)与相应的oj题
文章目录 一 栈栈的概念:栈的实现:栈的数组实现默认构造方法压栈获取栈元素的个数出栈获取栈顶元素判断当前栈是否为空 java提供的Stack类Stack实现的接口: LinkedList也可以当Stack使用虚拟机栈,栈帧,栈的三个概念 二 栈的一些算…...
linux修改时区为CST
目录 第一步: 第二步: 第三步: 第一步: 备份原来的时区信息 [rootlocalhost ~]# mv /etc/localtime localtime.bak 第二步: 通过软链接将亚洲/上海 的时区信息 指导时区信息 [rootlocalhost ~]# ln -s /usr/share…...
【Spring Security】初识Spring Security
今天晚上因为一个项目问题,而正式开始学习Spring Security。 这个问题是“APP端的操作员应仅可查看管理后台的项目负责人分配给自己的计划”。 一、Spring Security的核心组件: Spring Security的核心组件包括:SecurityContextHolder、Auth…...
配置单区域OSPF
目录 引言 一、搭建基础网络 1.1 配置网络拓扑图如下 1.2 IP地址表 二、测试每个网段都能单独连通 2.1 PC0 ping通Router1所有接口 2.2 PC1 ping通Router1所有接口 2.3 PC2 ping通Router2所有接口 2.4 PC3 ping通Router2所有接口 2.5 PC4 ping通Router3所有接口 2.…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
