/*
@param k: from 1 to N;
@param val: val>=0
*/
int findKthDigit(int val, int k) {
string str = to_string(val);
int len = str.length();
if(len < k || k <= 0) return -1;
return str[len-k] + '0';
}
int findKthDigit(int val, int k) {
if(k <= 0) return -1;
if(val <= 0) return -1;
if(val % (int)pow(10, k) < (int)pow(10, k-1)) return -1;
return val % (int)pow(10, k) / (int)pow(10,k-1);
}
给定一个数组,求数组中第三大的元素
class Solution {
public:
int thirdMax(vector<int>& nums) {
int len = nums.size();
if(len == 0) return INT_MIN;
if(len == 1) return nums[0];
if(len == 2) return max(nums[0], nums[1]);
//去除重复的元素
sort(nums.begin(), nums.end());
vector<int>::iterator it = unique(nums.begin(), nums.end());
nums.resize(distance(nums.begin(), it));
if(nums.size() < 3) {
return *(nums.end()-1);
}
return *(nums.end()-3);
}
};
class Solution {
public:
int thirdMax(vector<int>& nums) {
set<int> top3;
for (int num : nums) {
top3.insert(num);
if (top3.size() > 3)
top3.erase(top3.begin());
}
return top3.size() == 3 ? *top3.begin() : *top3.rbegin();
}
};
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: The root of binary tree
* @return root of new tree
*/
void helper(TreeNode* src, TreeNode** dest) {
if(src == NULL) return ;
TreeNode* tmp = new TreeNode(-1);
tmp->val = src->val;
*dest = tmp;
if(src->left) {
helper(src->left, &((*dest)->left));
}
if(src->right) {
helper(src->right, &((*dest)->right));
}
}
TreeNode* cloneTree(TreeNode *root) {
if(root == NULL) return NULL;
TreeNode* head = new TreeNode(-1);
head->val = root->val;
if(root->left) {
helper(root->left, &(head->left));
}
if(root->right) {
helper(root->right, &(head->right));
}
return head;
}
};
给出n,生成所有由1...n为节点组成的不同的二叉查找树 给出n = 3,生成所有5种不同形态的二叉查找树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @paramn n: An integer
* @return: A list of root
*/
vector<TreeNode* > createTrees(int start, int end) {
vector<TreeNode*> res;
if(start > end) {
res.push_back(NULL);
return res;
}
if(start == end) {
res.push_back(new TreeNode(start));
return res;
}
for(int i=start;i<=end;i++) {
vector<TreeNode*> left = createTrees(start, i-1);
vector<TreeNode*> right = createTrees(i+1, end);
for(auto l:left) {
for(auto r:right) {
TreeNode* head = new TreeNode(i);
head->left = l;
head->right = r;
res.push_back(head);
}
}
}
return res;
}
vector<TreeNode *> generateTrees(int n) {
// write your code here
vector<TreeNode*> res = createTrees(1, n);
return res;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie trie;
* trie.insert("lintcode");
* trie.search("lint"); will return false
* trie.startsWith("lint"); will return true
*/
class TrieNode {
public:
// Initialize your data structure here.
TrieNode() {
isWord = false;
for(auto &a : alpha) {
a = NULL;
}
}
public:
TrieNode* alpha[26];
bool isWord;
};
class Trie {
public:
Trie() {
root = new TrieNode();
}
// Inserts a word into the trie.
void insert(string word) {
TrieNode* p = root;
for(auto c:word) {
if(p->alpha[c-'a'] == NULL) {
p->alpha[c-'a'] = new TrieNode();
}
p = p->alpha[c-'a'];
}
p->isWord = true;
}
// Returns if the word is in the trie.
bool search(string word) {
TrieNode* p = root;
for(auto c:word) {
if(p && p->alpha[c-'a']) {
p = p->alpha[c-'a'];
} else {
return false;
}
}
return p->isWord;
}
// Returns if there is any word in the trie
// that starts with the given prefix.
bool startsWith(string prefix) {
TrieNode* p = root;
for(auto c:prefix) {
if(p && p->alpha[c-'a']) {
p = p->alpha[c-'a'];
} else {
return false;
}
}
return true;
}
private:
TrieNode* root;
};
class TrieNode {
public:
// Initialize your data structure here.
TrieNode() {
isWord = false;
for(auto &a : alpha) {
a = NULL;
}
}
public:
TrieNode* alpha[26];
bool isWord;
};
class WordDictionary {
public:
WordDictionary() {
root = new TrieNode();
}
// Adds a word into the data structure.
void addWord(string word) {
// Write your code here
TrieNode* p = root;
for(auto c:word) {
if(p->alpha[c-'a'] == NULL) {
p->alpha[c-'a'] = new TrieNode();
}
p = p->alpha[c-'a'];
}
p->isWord = true;
}
// Returns if the word is in the data structure. A word could
// contain the dot character '.' to represent any one letter.
bool search(string word) {
// Write your code here
return search(word, root, 0);
}
bool search(string &word, TrieNode* node, int pos) {
if(pos == word.size()) return node->isWord;
if(word[pos] == '.') {
for(auto r:node->alpha) {
if(r && search(word, r, pos+1)) return true;
}
return false;
} else {
return node->alpha[word[pos]-'a'] && search(word, node->alpha[word[pos]-'a'], pos+1);
}
return false;
}
private:
TrieNode* root;
};
// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary;
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
void dfs(int m, int residue, const vector<int>& A, vector<bool>& selected,
int &maxSum, int start) {
if(residue >= 0) {
maxSum = max(maxSum, m - residue);
}
for(int i=start;i<A.size();i++) {
if(selected[i] == false && A[i] <= residue) {
selected[i] = true;
dfs(m, residue - A[i], A, selected, maxSum, i+1);
selected[i] = false;
}
}
}
int backPack(int m, vector<int> A) {
// write your code here
vector<bool> selected(A.size(), false);
int maxSum = 0;
dfs(m, m, A, selected, maxSum, 0);
return maxSum;
}
};
- 这段代码是使用的思路就是暴力求解,进行深度优先遍历,遍历所有解空间,那必定会超时
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
void dfs(int m, int residue, const vector<int>& A, vector<bool>& selected,
int &maxSum, int start) {
if(residue >= 0) {
maxSum = max(maxSum, m - residue);
}
for(int i=start;i<A.size();i++) {
if(selected[i] == false && A[i] <= residue) {
selected[i] = true;
dfs(m, residue - A[i], A, selected, maxSum, i+1);
selected[i] = false;
}
}
}
int backPack(int m, vector<int> A) {
// write your code here
//vector<bool> selected(A.size(), false);
int maxSum = 0;
//dfs(m, m, A, selected, maxSum, 0);
/*
dp[i,j] : 前i个物品放入容量为j的背包中的最大重量是
dp[i,j] = max(dp[i-1,j-A[i]] + A[i], dp[i-1, j])
*/
int N = A.size();
vector<vector<int>> dp(N+1, vector<int>(m+1,0));
for(int i=1;i<=N;i++) {
for(int j=1;j<=m;j++) {
if(j - A[i-1] >= 0)
dp[i][j] = max(dp[i-1][j-A[i-1]] + A[i-1], dp[i-1][j]);
else
dp[i][j] = max(dp[i][j], dp[i-1][j]);
}
}
maxSum = dp[N][m];
return maxSum;
}
};
- 将上述问题转化为二维动态规划问题,但是在最后却只通过了80%的测试用例,还要继续优化!
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
void dfs(int m, int residue, const vector<int>& A, vector<bool>& selected,
int &maxSum, int start) {
if(residue >= 0) {
maxSum = max(maxSum, m - residue);
}
for(int i=start;i<A.size();i++) {
if(selected[i] == false && A[i] <= residue) {
selected[i] = true;
dfs(m, residue - A[i], A, selected, maxSum, i+1);
selected[i] = false;
}
}
}
int backPack(int m, vector<int> A) {
// write your code here
//vector<bool> selected(A.size(), false);
int maxSum = 0;
//dfs(m, m, A, selected, maxSum, 0);
/*
dp[i,j] : 前i个物品放入容量为j的背包中的最大重量是
dp[i,j] = max(dp[i-1,j-A[i]] + A[i], dp[i-1, j])
*/
/*
对上述的动态规划方程进行优化
dp[i]仅仅和dp[i-1]的状态相关
且,每次在迭代时,需要从m开始遍历,这会将更加便于操作
*/
int N = A.size();
vector<int> dp(m+1, 0);
for(int i=0;i<N;i++) {
for(int j=m;j>=0;j--) {
if(j - A[i] >= 0)
dp[j] = max(dp[j-A[i]] + A[i], dp[j]);
}
}
maxSum = dp[m];
return maxSum;
}
};
给出n个物品的体积A[i]和其价值V[i],将他们装入一个大小为m的背包,最多能装入的总价值有多大?
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A & V: Given n items with size A[i] and value V[i]
* @return: The maximum value
*/
/*
dp[i,j] : 存储当前i个物体存储到容量问j的包中,所最大的价值
dp[i,j] = {dp[i-1, j-A[i]] + val[i], dp[i-1,j]}
*/
int backPackIII(int m, vector<int> A, vector<int> V) {
int N = A.size();
vector<int> dp(m+1, 0);
for(int i=0;i<N;i++) {
for(int j=m;j>=0;j--) {
if(j - A[i] >= 0) {
dp[j] = max(dp[j], dp[j-A[i]] + V[i]);
}
}
}
return dp[m];
}
int backPackII(int m, vector<int> A, vector<int> V) {
// write your code here
return backPackIII(m, A, V);
int N = A.size();
vector<vector<int>> dp(N+1, vector<int>(m+1, 0));
for(int i=1;i<=N;i++) {
for(int j=m;j>=0;j--) {
if(j - A[i-1] >= 0) {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-A[i-1]] + V[i-1]);
}
dp[i][j] = max(dp[i][j], dp[i-1][j]);
}
}
return dp[N][m];
}
};
给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
class Solution {
public:
/**
* @param A, B: Two strings.
* @return: The length of longest common subsequence of A and B.
*/
/*
动态规划
dp[i,j] : A[i], B[j]的最长公共子序列的长度
dp[i,j] = {
dp[i-1,j-1] + 1, if(A[i] == B[j])
max(dp[i-1,j], dp[i,j-1]), if(A[i] != B[j])
}
*/
int longestCommonSubsequence(string A, string B) {
// write your code here
int res = 0;
int lA = A.size(), lB = B.size();
vector<vector<int> > dp(lA+1, vector<int>(lB+1, 0));
for(int i=1;i<=lA;i++) {
for(int j=1;j<=lB;j++) {
if(A[i-1] == B[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
res = dp[lA][lB];
return res;
}
};
Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.
class Solution {
public:
/**
* @param nums an integer array and all positive numbers, no duplicates
* @param target an integer
* @return an integer
*/
void helper(vector<int> &nums, int residue, int &cnt, vector<int> &cur) {
if(residue == 0) {
if(table.count(cur) == 0) {
cnt++;
table.insert(cur);
}
} else {
for(int i=0;i<nums.size();i++) {
if(residue - nums[i] >= 0) {
cur.push_back(nums[i]);
helper(nums, residue - nums[i], cnt, cur);
cur.pop_back();
}
}
}
}
/*
dp[i] : 含义是当容量为i时,有多少种装包的方法
dp[i] = {
if(cur_obj <= i) {
dp[i] += dp[i-cur_obj];
}
}
*/
int helper02(vector<int>& nums, int target) {
vector<int> dp(target+1, 0);
dp[0] = 1;
for(int i=1;i<=target;i++) {
for(auto a:nums) {
if(i>=a) {
dp[i] += dp[i-a];
}
}
}
return dp[target];
}
int backPackVI(vector<int>& nums, int target) {
// Write your code here
int N = nums.size();
if(N == 0) return 0;
if(N == 1 && nums[0] != target) return 0;
int cnt = 0;
//vector<int> cur;
//helper(nums, target, cnt, cur);
cnt = helper02(nums, target);
return cnt;
}
private:
set<vector<int>> table;
};
给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组。
class Solution {
public:
/**
* @param A: An integer array.
* @return: void
*/
void rerange(vector<int> &A) {
// write your code here
int N = A.size();
int r = 1, l = N-1;
while(r<N) {
while(r<N && A[r] * A[r-1] < 0) {
r++;
}
int l = r;
if(A[r] > 0) {
while(l<N && A[l]>0) l++;
} else {
while(l<N && A[l]<0) l++;
}
if(l<N) {
swap(A[r], A[l]);
}
if(A[r] * A[r-1] > 0) {
A.insert(A.begin(), A[N-1]);
A.pop_back();
break;
}
}
}
};
给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大。每个子数组的数字在数组中的位置应该是连续的。返回最大的和。
给出数组 [1, 3, -1, 2, -1, 2] 这两个子数组分别为 [1, 3] 和 [2, -1, 2] 或者 [1, 3, -1, 2] 和 [2],它们的最大和都是 7。
class Solution {
public:
/**
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
int helper(vector<int>& nums, int start, int end) {
if(start > end) {
return 0;
}
int curSum = 0, maxSum = nums[start];
for(int i=start;i<=end;i++) {
curSum = max(curSum + nums[i], nums[i]);
maxSum = max(maxSum, curSum);
}
return maxSum;
}
/*
先计算,左边数组中的最大连续子数组的和,并保存起来
在计算右边连最大续子数组的和,并逐渐与左边相应的位置的最大和求和进行比较
得到全局最大的数组的和
*/
int helper02(vector<int>& nums) {
vector<int> left(nums.size(), 0);
int local = 0, global = INT_MIN;
for(int i=0;i<nums.size();i++) {
local = max(local + nums[i], nums[i]);
global = max(global, local);
left[i] = global;
}
local = 0, global = INT_MIN;
int res = INT_MIN;
for(int i=nums.size()-1;i>=0;i--) {
if(i < nums.size()-1) {
res = max(res, left[i] + global);
}
local = max(local + nums[i], nums[i]);
global = max(global, local);
}
return res;
}
int maxTwoSubArrays(vector<int> nums) {
// write your code here
// int res = INT_MIN;
// for(int i=0;i<nums.size()-1;i++) {
// int a = helper(nums, 0, i);
// int b = helper(nums, i+1, nums.size()-1);
// res = max(res, a + b);
// }
return helper02(nums);
}
};
假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。
class Solution {
public:
/**
* @param prices: Given an integer array
* @return: Maximum profit
*/
int maxProfit(vector<int> &prices) {
// write your code here
int start = 0, end = prices.size();
int res = 0;
for(int i=0;i<end-1;i++) {
if(prices[i] < prices[i+1]) {
res += (prices[i+1] - prices[i]);
}
}
return res;
}
};
假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来找到最大的利润。你最多可以完成两笔交易。
class Solution {
public:
/**
* @param prices: Given an integer array
* @return: Maximum profit
*/
int maxProfit(vector<int> &prices) {
// write your code here
int N = prices.size();
if(N == 0 || N == 1) return 0;
vector<int> left(N, 0);
vector<int> right(N, 0);
//求在i时刻卖出时的最大收益(0-i),这里要记录截止到i-1时刻的最低价格
int minRes = prices[0];
for(int i=1;i<N;i++) {
if(minRes < prices[i]) {
left[i] = max(left[i-1], prices[i] - minRes);
} else {
minRes = min(minRes, prices[i]);
left[i] = left[i-1];
}
}
//求在i时刻买入时的最大收益(i-N),这里要记录截止到i时刻的最高价格
int maxRes = prices[N-1];
for(int i=N-2;i>=0;i--) {
if(maxRes > prices[i]) {
right[i] = max(right[i+1], maxRes - prices[i]);
} else {
maxRes = max(maxRes, prices[i]);
right[i] = right[i+1];
}
}
//求最多两次交易的最大收益
int res = 0;
for(int i=0;i<N;i++) {
res = max(res, left[i] + right[i]);
}
return res;
}
};
给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大。输出答案时,请分别返回第一个数字和最后一个数字的下标。(如果两个相同的答案,请返回其中任意一个)
class Solution {
public:
/**
* @param A an integer array
* @return A list of integers includes the index of
* the first number and the index of the last number
*/
vector<int> continuousSubarraySum(vector<int>& A) {
// Write your code here
int maxSum = A[0], tmpSum = A[0];
int start = 0, end = 0, tmpStart = 0;
for(int i=1;i<A.size();i++) {
if(tmpSum + A[i] < A[i]) {
tmpStart = i;
}
tmpSum = max(tmpSum + A[i], A[i]);
maxSum = max(maxSum, tmpSum);
if(maxSum == tmpSum) {
end = i;
start = tmpStart;
}
}
// cout << maxSum << endl;
vector<int> res = {start, end};
return res;
}
};
组给出两个整数n和k,返回从1......n中选出的k个数的组合。
class Solution {
public:
/**
* @param n: Given the range of numbers
* @param k: Given the numbers of combinations
* @return: All the combinations of k numbers out of 1..n
*/
void helper(int n, int k, vector<int>& data, int start) {
if(data.size() == k) {
table.push_back(data);
return ;
}
if(data.size() < k) {
for(int i=start;i<=n;i++) {
data.push_back(i);
helper(n, k, data, i+1);
data.pop_back();
}
}
}
vector<vector<int> > combine(int n, int k) {
// write your code here
vector<int> data;
helper(n, k, data, 1);
return table;
}
private:
vector<vector<int> > table;
};
给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。 例如,给出候选数组[2,3,6,7]和目标数字7,所求的解为: [7], [2,2,3]
class Solution {
public:
/**
* @param candidates: A list of integers
* @param target:An integer
* @return: A list of lists of integers
*/
inline string vec2string(vector<int> &data) {
string res;
for(auto a:data) {
res += (to_string(a) + "#");
}
return res;
}
void helper(vector<int>& candidates, int target, vector<int>& res) {
if(target == 0) {
string a = vec2string(res);
if(hash.count(a) == 0) {
table.push_back(res);
hash.insert(a);
}
return ;
}
if(target > 0) {
for(int i=0;i<candidates.size();i++) {
if(candidates[i] <= target) {
if(res.size() == 0) {
res.push_back(candidates[i]);
helper(candidates, target - candidates[i], res);
res.pop_back();
} else if(candidates[i] >= res[res.size()-1]) {
res.push_back(candidates[i]);
helper(candidates, target - candidates[i], res);
res.pop_back();
}
}
}
}
}
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
// write your code here
vector<int> res;
sort(candidates.begin(), candidates.end());
helper(candidates, target, res);
return table;
}
private:
vector<vector<int> > table;
set<string> hash;
};