首页 > 编程语言 >【综合算法练习】(第八篇)

【综合算法练习】(第八篇)

时间:2024-10-29 12:48:18浏览次数:7  
标签:digits nums 第八篇 练习 pos ret 算法 dfs path

目录

全排列Ⅱ(medium)

题目解析

讲解算法原理

编写代码

电话号码的字⺟组合(medium)

题目解析

讲解算法原理

编写代码


全排列Ⅱ(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个可包含重复数字的序列nums,按任意顺序返回所有不重复的全排列。
• ⽰例1:
输⼊:nums=[1,1,2]输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
• ⽰例2:
输⼊:nums=[1,2,3]输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
• 提⽰:
1<=nums.length<=8
-10<=nums[i]<=10

讲解算法原理

解法:算法思路:

因为题⽬不要求返回的排列顺序,因此我们可以对初始状态排序,将所有相同的元素放在各⾃相邻的
位置,⽅便之后操作。因为重复元素的存在,我们在选择元素进⾏全排列时,可能会存在重复排列,例如:[1,2,1],所有的下标排列为:

123
132
213
231
312
321

按照以上下标进⾏排列的结果为:

121
112
211
211
112
121 

可以看到,有效排列只有三种[1,1,2],[1,2,1],[2,1,1],其中每个排列都出现两次。因此,我们需要对相同元素定义⼀种规则,使得其组成的排列不会形成重复的情况:
1. 我们可以将相同的元素按照排序后的下标顺序出现在排列中,通俗来讲,若元素s出现x次,则排序后的第2个元素s⼀定出现在第1个元素s后⾯,排序后的第3个元素s⼀定出现在第2个元素s后⾯,以此类推,此时的全排列⼀定不会出现重复结果。
2. 例如:a1=1,a2=1,a3=2,排列结果为[1,1,2]的情况只有⼀次,即a1在a2前⾯,因为a2不会出现在a1前⾯从⽽避免了重复排列。

3. 我们在每⼀个位置上考虑所有的可能情况并且不出现重复;

4. *注意*:若当前元素的前⼀个相同元素未出现在当前状态中,则当前元素也不能直接放⼊当前状态的数组,此做法可以保证相同元素的排列顺序与排序后的相同元素的顺序相同,即避免了重复排列出现。
5. 通过深度优先搜索的⽅式,不断地枚举每个数在当前位置的可能性,并在递归结束时回溯到上⼀个状态,直到枚举完所有可能性,得到正确的结果。
递归函数设计:voidbacktrack(vector<int>&nums,intidx)参数:idx(当前需要填⼊的位置);
返回值:⽆;函数作⽤:查找所有合理的排列并存储在答案列表中。
递归流程如下:1. 定义⼀个⼆维数组ans⽤来存放所有可能的排列,⼀个⼀维数组perm⽤来存放每个状态的排列,⼀个⼀维数组visited标记元素,然后从第⼀个位置开始进⾏递归;

2. 在每个递归的状态中,我们维护⼀个步数idx,表⽰当前已经处理了⼏个数字;

3. 递归结束条件:当idx等于nums数组的⻓度时,说明我们已经处理完了所有数字,将当前数组存⼊结果中;

4. 在每个递归状态中,枚举所有下标i,若这个下标未被标记,并且在它之前的相同元素被标记过,则使⽤nums数组中当前下标的元素:

a. 将visited[i]标记为1;
b. 将nums[i]添加⾄perm数组末尾;

c. 对第step+1个位置进⾏递归;
d. 将visited[i]重新赋值为0,并删除perm末尾元素表⽰回溯;

5. 最后,返回ans。 

编写代码

c++算法代码:
 

class Solution
{
 vector<int> path;
 vector<vector<int>> ret;
 bool check[9];
public:
 vector<vector<int>> permuteUnique(vector<int>& nums) 
 {
 sort(nums.begin(), nums.end());
 dfs(nums, 0);
 return ret;
 }
 void dfs(vector<int>& nums, int pos)
 {
 if(pos == nums.size())
 {
 ret.push_back(path);
 return;
 }
 for(int i = 0; i < nums.size(); i++)
 {
 // 剪枝
 if(check[i] == false && (i == 0 || nums[i] != nums[i - 1] || 
check[i - 1] != false))
 {
 path.push_back(nums[i]);
 check[i] = true;
 dfs(nums, pos + 1);
 path.pop_back(); // 恢复现场
 check[i] = false;
 }
 
 }
 }
};

java算法代码:

class Solution
{
 List<Integer> path;
 List<List<Integer>> ret;
 boolean[] check;
 public List<List<Integer>> permuteUnique(int[] nums) 
 {
 path = new ArrayList<>();
 ret = new ArrayList<>();
 check = new boolean[nums.length];
 Arrays.sort(nums);
 dfs(nums, 0);
 return ret;
 }
 public void dfs(int[] nums, int pos)
 {
 if(pos == nums.length)
 {
 ret.add(new ArrayList<>(path));
 return;
 }
 for(int i = 0; i < nums.length; i++)
 {
 // 剪枝
 if(check[i] == false && (i == 0 || nums[i] != nums[i - 1] || 
check[i - 1] != false))
 {
 path.add(nums[i]);
 check[i] = true;
 dfs(nums, pos + 1);
 // 回溯 -> 恢复现场
 path.remove(path.size() - 1);
 check[i] = false;
 }
 }
 }
}

电话号码的字⺟组合(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个仅包含数字2-9的字符串,返回所有它能表⽰的字⺟组合。答案可以按任意顺序返回。给出数字到字⺟的映射如下(与电话按键相同)。注意1不对应任何字⺟。
• ⽰例1:
输⼊:digits="23"输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
• ⽰例2:
输⼊:digits=""输出:[]
• ⽰例3:
输⼊:digits="2"输出:["a","b","c"]
• 提⽰:
0<=digits.length<=4
digits[i]是范围['2','9']的⼀个数字。

讲解算法原理

解法:
算法思路:

每个位置可选择的字符与其他位置并不冲突,因此不需要标记已经出现的字符,只需要将每个数字对应的字符依次填⼊字符串中进⾏递归,在回溯是撤销填⼊操作即可。
• 在递归之前我们需要定义⼀个字典phoneMap,记录2~9各⾃对应的字符。
递归函数设计:voidbacktrack(unordered_map<char,string>&phoneMap,string&digits,intindex)
参数:index(已经处理的元素个数),ans(字符串当前状态),res(所有成⽴的字符串);返回值:⽆
函数作⽤:查找所有合理的字⺟组合并存储在答案列表中。
递归函数流程如下:
1. 递归结束条件:当index等于digits的⻓度时,将ans加⼊到res中并返回;
2. 取出当前处理的数字digit,根据phoneMap取出对应的字⺟列表letters;
3. 遍历字⺟列表letters,将当前字⺟加⼊到组合字符串ans的末尾,然后递归处理下⼀个数字(传⼊index+1,表⽰处理下⼀个数字);
4. 递归处理结束后,将加⼊的字⺟从ans的末尾删除,表⽰回溯。
5. 最终返回res即可。

编写代码

c++算法代码:

class Solution
{
 string hash[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", 
"tuv", "wxyz"};
 string path;
 vector<string> ret;
public:
 vector<string> letterCombinations(string digits) 
 {
 if(digits.size() == 0) return ret;
 dfs(digits, 0);
 return ret;
 }
 void dfs(string& digits, int pos)
 {
 if(pos == digits.size())
 {
 ret.push_back(path);
 return;
 }
 for(auto ch : hash[digits[pos] - '0'])
 {
 path.push_back(ch);
 dfs(digits, pos + 1);
 path.pop_back(); // 恢复现场
 }
 }
};

java算法代码:

class Solution
{
 String[] hash = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", 
"wxyz"};
 List<String> ret;
 StringBuffer path;
 public List<String> letterCombinations(String digits) 
 {
 ret = new ArrayList<>();
 path = new StringBuffer();
 if(digits.length() == 0) return ret;
 dfs(digits, 0);
 return ret;
 }
 public void dfs(String digits, int pos)
 {
 if(pos == digits.length())
 {
 ret.add(path.toString());
 return;
 }
 String cur = hash[digits.charAt(pos) - '0'];
 for(int i = 0; i < cur.length(); i++)
 {
 path.append(cur.charAt(i));
 dfs(digits, pos + 1);
 path.deleteCharAt(path.length() - 1); // 恢复现场 }
 }
}

标签:digits,nums,第八篇,练习,pos,ret,算法,dfs,path
From: https://blog.csdn.net/weixin_73861555/article/details/143326290

相关文章

  • 10.29课堂练习 AI内心独白法的使用
    在语文课堂中,向学生提问《学弈》一文中,为什么两个学生虽然一起学习下棋,但最终的学习效果却大相径庭,即“虽与之俱学,弗若之矣”,可能会得到学生以下几种回答:学生回答一:回答内容:可能是因为其中一个学生天赋比较高,所以学得快,而另一个学生天赋较差,所以学得慢。老师评价:这种回答强调了......
  • 从零开始学五笔(十):练习
    前面我们花了那么多篇幅去学习五笔的规则,并讲解了如何用五笔输入各种汉字,接下来就是练习了。我强烈建议专门抽出几天来练习五笔,达到能打大部分字的程度,然后我们就可以放下拼音,开始在日常中使用五笔了。而随着使用的时间增长,打字也会越来越熟练。‍怎么练习?基本方法论:熟悉规......
  • 百度二面算法:合法的括号字符串
    目录标题1.题目1.1示例2.利用栈求解2.1代码结构分析2.1.1代码优缺点1.题目给定一个字符串s,字符串s只包含以下三种字符:(,*,),请你判断s是不是一个合法的括号字符串。合法括号字符串有如下规则:左括号’(‘必须有对应的右括号’)’右括号’)‘必须有对应的左括号......
  • 算法与数据结构——计数排序
    计数排序计数排序(countingsort)通过统计元素数量来实现排序,通常应用于整数数组。简单实现给定一个长度为n的数组nums,其中的元素都是“非负整数”,计数排序的整体流程如下:遍历数组,找出其中最大的数组,记为m,然后创建一个长度为m+1的辅助数组counter。借助counter统计nums中各......
  • 抖音中aBogus签名算法的纯Python代码实现(2024年10月)
    目前网上的aBogus签名算法都是用python里execjs来执行js代码计算的,这种方法虽然可以达到计算签名值的结果,但是性能不高。本文直接将aBogus的js的源码改成python代码,同样的参数,计算的结果和js版本一样。附python源码importjsonfromrandomimportchoicefromrandomimport......
  • 【C++】—— priority_queue :平衡效率与秩序的算法利器
    去感受一棵草、一缕风、一场日落,去重新触摸真正的生活。——高盛元目录1、优先级队列1.1什么是优先级队列1.2 priority_queue的使用1.3仿函数2、priority_queue的模拟实现2.1整体框架接口2.2插入&&向上调整2.2删除&&向下调整2.3其他接口2.4优先级队列的应用......
  • 对称加密算法和非对称加密算法
    目录对称加密(SymmetricEncryption)非对称加密(AsymmetricEncryption)对比分析应用场景RSA加密算法是一种非对称加密算法。AES算法全称AdvancedEncryptionStandard,又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且......
  • RSA加密算法实现
    Java实现RSA加密算法示例,包括密钥对的生成、加密和解密过程。首先需要导入Java的加密库,这些功能主要通过java.security和javax.crypto包提供。先生成了一个RSA密钥对,包括一个公钥和一个私钥。然后使用公钥加密了一个字符串,并使用私钥解密了加密后的字符串。加密和解密的结果都......
  • 算法的学习笔记—滑动窗口的最大值(牛客JZ59)
    ......
  • 机器学习实战——基于粒子群优化算法(PSO)优化支持向量回归(SVR)模型(附完整代码)
    基于粒子群优化算法优化支持向量回归模型(附完整代码)关于作者作者:小白熊作者简介:精通python、matlab、c#语言,擅长机器学习,深度学习,机器视觉,目标检测,图像分类,姿态识别,语义分割,路径规划,智能优化算法,数据分析,各类创新融合等等。联系邮箱:[email protected]科研辅导、知识付......