Leetcode 编程中好用的一些C++用法
1.取vector的子集
vector<int>(vc.begin() + 1, vc.end())
这里是指,取vc.begin()+1到末尾的所有元素,从而形成一个新的vector数组。例如:
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 int main() 7 { 8 vector<int> vc; 9 vc.resize(10,0); 10 for (int i = 0; i < 10; i++) { 11 vc[i] = i; 12 } 13 for (int j = 0; j < (vector<int>(vc.begin() + 1, vc.end())).size(); j++) 14 cout << (vector<int>(vc.begin() + 1, vc.end()))[j] << endl; 15 return 0; 16 }
此种用法,在分治或递归思想中用的较多,如下一道题:
654. 最大二叉树
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
代码如下:
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 private: 12 TreeNode* helper(const vector<int>& nums) 13 { 14 auto it = max_element(nums.begin(), nums.end()); 15 if (it == nums.end()) return nullptr; 16 TreeNode* root = new TreeNode(*it); 17 root->left = helper(vector<int>(nums.begin(), it)); 18 root->right = helper(vector<int>(it + 1, nums.end())); 19 20 return root; 21 } 22 public: 23 TreeNode* constructMaximumBinaryTree(vector<int>& nums) { 24 TreeNode* root = helper(nums); 25 26 return root; 27 } 28 };
思想:
每次找到vector中的最大值,这里用的是max_element()函数,然后递归构建前半个数组,即
vector<int>(nums.begin(), it) 和 后半个数组,即
vector<int>(it + 1, nums.end())
2.STL中的max_element函数
函数功能:指向序列之中数组最大元素,包含在algorithm库中。
函数返回迭代器,时间复杂度O(n)。
函数原型如下所示:
213. 打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 1:
输入: [2,3,2]
输出: 3
解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
分析:
环状结构可以理解为返回前(n-1)和后(n-1)中的最大金额中的最大值!
1 class Solution { 2 public: 3 int rob(vector<int>& nums) { 4 if(nums.size()==0) 5 return 0; 6 if(nums.size()==1) 7 return nums[0]; 8 return max(func((vector<int> (nums.begin(),nums.end()-1))),func((vector<int> (nums.begin()+1,nums.end())))); 9 } 10 11 int func(vector<int> nums){ 12 //返回nums中的最高金额 13 if(nums.size()==1) 14 return nums[0]; 15 if(nums.size()==2) 16 return max(nums[0],nums[1]); 17 vector<int> vc; 18 vc.resize(nums.size(),0); 19 vc[0]=nums[0]; 20 vc[1]=max(nums[0],nums[1]); 21 for(int i=2;i<nums.size();i++) 22 { 23 vc[i]=max(vc[i-1],nums[i]+vc[i-2]); 24 } 25 return vc[nums.size()-1]; 26 } 27 };
此处,也用到了vector的子数组,将vector子数组作为参数。
return max(func((vector<int> (nums.begin(),nums.end()-1))),func((vector<int> (nums.begin()+1,nums.end()))));
3.string和char之间的转换
1002. 查找常用字符
分析:
首先,创建一个二维数组,26列记录每个单词中a~z的个数,a~z的ASCII码值为97~122,因此下标为A[i][j]-97;
然后,统计每一列的最小值,初始值为0,如果某一个字母,有的单词中不存在,则该列中的最小值应该为0;
最后,根据最小值min,向结果集中填充min个字母,假定列为j,则填充的字母为 char(j+97)。
代码如下:
1 class Solution { 2 public: 3 vector<string> commonChars(vector<string>& A) { 4 vector<string> res; 5 //初始化二维数组 A.size() * 26 6 vector<vector<int>> vc; 7 vector<int> level; 8 level.resize(26,0); 9 vc.resize(A.size(),level); 10 11 //填表 12 for(int i=0;i<A.size();i++) 13 { 14 for(int j=0;j<A[i].length();j++) 15 { 16 vc[i][A[i][j]-97]++; 17 } 18 } 19 20 //统计最小值 21 int min; 22 string temp=""; 23 for(int j=0;j<26;j++){ 24 min=100; //初始化最小值,每个最小值不会超过100 25 for(int i=0;i<A.size();i++) 26 { 27 //每一列的最小值 28 if(vc[i][j]<min) 29 min=vc[i][j]; 30 } 31 //统计出最小值,在结果集中填充对应的字母个数 32 while(min--){ 33 temp.clear(); 34 temp.push_back(char(j+97)); 35 res.push_back(temp); 36 } 37 } 38 return res; 39 } 40 };
下边是可执行代码:
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 5 using namespace std; 6 vector<string> commonChars(vector<string>& A) { 7 vector<string> res; 8 //初始化二维数组 A.size() * 26 9 vector<vector<int>> vc; 10 vector<int> level; 11 level.resize(26, 0); 12 vc.resize(A.size(), level); 13 14 //填表 15 for (int i = 0; i < A.size(); i++) 16 { 17 for (int j = 0; j < A[i].length(); j++) 18 { 19 vc[i][A[i][j] - 97]++; 20 } 21 } 22 cout << "The array is as follow:" << endl; 23 for (int i = 0; i < 26; i++) 24 { 25 cout << char(i + 97) << " "; 26 } 27 cout << endl; 28 for (int i = 0; i < A.size(); i++) 29 { 30 for (int j = 0; j < 26; j++) 31 { 32 cout << vc[i][j]<<" "; 33 } 34 cout << endl; 35 } 36 37 //统计最小值 38 int min; 39 string temp = ""; 40 for (int j = 0; j < 26; j++) { 41 min = 100; //初始化最小值,每个最小值不会超过100 42 for (int i = 0; i < A.size(); i++) 43 { 44 //每一列的最小值 45 if (vc[i][j] < min) 46 min = vc[i][j]; 47 } 48 //统计出最小值,在结果集中填充对应的字母个数 49 while (min--) { 50 temp.clear(); 51 temp.push_back(char(j + 97)); 52 res.push_back(temp); 53 } 54 } 55 cout << "res is as follows" << endl; 56 for (int i = 0; i < res.size(); i++) 57 { 58 cout << "\"" <<res[i] <<"\" "; 59 } 60 cout << endl; 61 return res; 62 } 63 64 int main() 65 { 66 vector<string> aa; 67 int n; 68 cout << "Please input the number of words:" << endl; 69 cin >> n; 70 aa.resize(n); 71 cout << "Please input the each word:" << endl; 72 for (int i = 0; i < n; i++) 73 { 74 cin >> aa[i]; 75 } 76 commonChars(aa); 77 return 0; 78 }
执行结果如下:
由上图可知,对于e来说,每个单词中都包含一次,因此,e列的最小值为1,向结果集中填充1个“e”,对于o列,最小值为0,说明至少有一个单词中,不包含该字母,因此,该字母不会放入到结果集。
这里须注意,放入结果集的值string类型,而非char类型,直接放进去肯定是对的,但是char如何转string?
1 //统计出最小值,在结果集中填充对应的字母个数 2 while (min--) { 3 temp.clear(); 4 temp.push_back(char(j + 97)); 5 res.push_back(temp); 6 }
这部分代码中包含转换过程,将temp声明为了string类型,相当于一个vector<char>类型,因此可以直接将char类型的字母push_back进去,然后整体看作string类型,放入res中。
在CSDN上看的三种方式:
//1、构造函数里有个string(size_t,char) char x = 'a'; string s(1,x); //2、string初始化没char,但是push_back可以 string s; s.push_back(x); //3、string可以由char*初始化 char xx[2] = {x,0}; string s(xx)
4.string和char之间的转换
118. 杨辉三角
分析:
res[i][0]=res[i][i-1]=1;
res[i][j]=res[i-1][j-1]+res[i-1][j];
代码如下:
1 class Solution { 2 public: 3 vector<vector<int>> generate(int numRows) { 4 vector<vector<int>> res; 5 vector<int> level; 6 if(numRows==1) 7 { 8 level.push_back(1); 9 res.push_back(level); 10 return res; 11 } 12 for(int i=1;i<=numRows;i++) 13 { 14 level.resize(i); 15 for(int j=0;j<i;j++) 16 { 17 if(j==0 || j==i-1) 18 level[j]=1; 19 else{ 20 level[j]=res.back()[j-1]+res.back()[j]; 21 } 22 } 23 res.push_back(level); 24 } 25 return res; 26 } 27 };
注意点:
对于vector,最后一项我们可以用res[res.size()-1]来获取,同样,res.back()也是最后一项。
如上述代码所示,res为二维数组,所有,其最后一项返回值为一个一维数组,可以直接通过索引进行访问,level[j]=res.back()[j-1]+res.back()[j];