leetcode-23-DynamicProgramming-1
357. Count Numbers with Unique Digits
解题思路:
用arr[i]存放长度为i时,各位互不相同的数字的个数,所以arr[1]=10,arr[2]=9*9。(第一位要为1,第二位与第一位要不同)
arr[3] = arr[2]*8,所以arr[i]=arr[i-1]*(10 - (k-1))。之后求和就可以了。
int countNumbersWithUniqueDigits(int n) {
if (!n)
return 1;
if (n == 1)
return 10;
if (n == 2)
return 91;
int sum = 0;
int arr[n + 2];
arr[1] = 10;
arr[2] = 81;
for (int i = 3; i <= n; i++)
arr[i] = arr[i-1] * (11 - i);
for (int i = 1; i <= n; i++) {
sum += arr[i];
}
return sum;
}
5. Longest Palindromic Substring
解题思路:
这道题使用一个数组dp[i][j]存储子串s[i...j]是否为回文串。那么dp[i][i]=true(i = 0...n), dp[i][i-1]=true(i = 1...n)
其他为false。判断的时候,dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true)。同时,需要记录最长回文串的位置。
枚举子串时,从k=2开始到n。
string longestPalindrome(string s) {
if (s.length() < 2)
return s;
int left = 0;
int right = 0;
bool dp[s.length()][s.length()];
memset(dp, false, sizeof(dp));
dp[0][0] = true;
for (int i = 1; i < s.length(); i++) {
dp[i][i] = true;
dp[i][i-1] = true;
}
int i, j, k;
for (k = 2; k <= s.length(); k++) {
for (i = 0; i <= s.length() - k; i++) {
j = i - 1 + k;
if (s[i] == s[j] && dp[i+1][j-1] == true) {
dp[i][j] = true;
if (right - left + 1 < k) {
left = i;
right = j;
}
}
}
}
return s.substr(left, right - left + 1);
}
516. Longest Palindromic Subsequence
解题思路:
subsequence与substring的区别在于它可以是不连续的,此处的思路是:
用dp[i][j]存储子序列s[i...j]中最长回文串的长度。初始化时,除了dp[i][i]=1外,其它都置为0。
枚举子序列的长度,从2开始。所以如果s[i]==s[j],那么dp[i][j] = dp[i+1][j-1]+2;否则
dp[i][j] = max(dp[i-1][j], dp[i][j-1])。最后只要返回dp[0][n-1]就可以了。
int longestPalindromeSubseq(string s) {
if (s.size() < 2)
return s.size();
int dp[s.size()][s.size()];
for (int i = 0; i < s.size(); i++) {
for (int j = 0; j < s.size(); j++) {
dp[i][j] = 0;
}
dp[i][i] = 1;
}
int i, j, k;
for (k = 1; k < s.size(); k++) {
for (i = 0; i < s.size() - k; i++) {
j = i + k;
if (s[i] == s[j])
dp[i][j] = dp[i+1][j-1] + 2;
else
dp[i][j] = dp[i+1][j] > dp[i][j-1] ? dp[i+1][j] : dp[i][j-1];
}
}
return dp[0][s.size()-1];
}
368. Largest Divisible Subset
解题思路:
这道题类似于求最长递增子序列。。考虑的是,大的数整除小的数,所以现将数组排序。然后用dp[i]记录以第i个数结尾的最长可整除子集的长度。
那么状态转移方程为:dp[i] = max{dp[j] + 1},j = 0...i-1。同时,要求dp[j]%dp[i]==0。另外,因为需要记录子集的内容,所以使用另一个
数组set来保留加入的序号(针对nums的),使用max记录最大长度,last记录最后一个序号。
需要注意的是,C++中数组的赋值,不能用int dp[n] = {1},因为这样只将dp[0]赋值为1,其他为0;也不能用memset,很奇怪==
vector<int> largestDivisibleSubset(vector<int>& nums) {
if (nums.size() < 2)
return nums;
// sort
sort(nums.begin(), nums.end());
// this way, only get 1,0,0
//int dp[nums.size()] = {1};
int dp[nums.size()];
// wrong!
//memset(dp, 1, nums.size());
int set[nums.size()];
for (int i = 0; i < nums.size(); i++) {
dp[i] = 1;
set[i] = -1;
}
int max = 0;
int last = -1;
vector<int> result;
for (int i = 1; i < nums.size(); i++) {
for (int j = 0; j < i; j++) {
if (nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
set[i] = j;
}
if (dp[i] > max) {
max = dp[i];
last = i;
}
}
}
// get result
for (int i = last; i >= 0;) {
result.insert(result.begin(), nums[i]);
i = set[i];
}
return result;
}
494. Target Sum
解题思路:
可以将所有数字分为两个组,positive和negative,那么
positive - negative = target
positive + negative = sum
所以两式相加,2postive = target + sum。所以可以把所有数字变为原来的两倍,选其中一部分数字作为positive,剩下的自然是negative,
看有多少种选法可以使得总和为target+sum。因此使用数组dp[i]来记录总和达到i的方法数。注意:
1) 初始化dp[0] = 1
2) 只考虑j>=nums[i]的情况,而且j要从target开始,不能从0开始,否则会WA
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for(int i = 0; i < nums.size(); i++) {
sum += nums[i];
nums[i] *= 2;
}
if (sum < S)
return 0;
int target = sum + S;
int dp[target + 1];
// initialize
dp[0] = 1;
for (int i = 0; i < nums.size(); i++) {
// ATTENTION: j
for (int j = target; j >= 0; j--) {
if (j >= nums[i]) {
dp[j] += dp[j - nums[i]];
}
}
}
return dp[target];
}
343. Integer Break
解题思路:
首先n=2时返回1,n=3时返回2,这两个需要特别考虑。然后用result[i]存储和为i时乘积最大值,因此
result[i]=max{result[i-3]*3, result[i-2]*2}。而关于result[2]和result[3]的值,需要观察。。
i = 4, max(1*3, 2*2) = 4
i = 5, max(result[2]*3, result[3]*2) = max(2*3, 3*2) = 6
i = 6, max(result[3]*3, result[4]*2) = max(3*3, 4*2) = 9
因此,result[2] = 2, result[3] = 3
int integerBreak(int n) {
int result[n+1] = {0};
if (n <= 3)
return n-1;
result[2] = 2;
result[3] = 3;
for (int i = 4; i <= n; i++) {
result[i] = 3 * result[i-3] > 2 * result[i-2] ? 3 * result[i-3] : 2 * result[i-2];
}
return result[n];
}
486. Predict the Winner
https://leetcode.com/problems/predict-the-winner/#/description
简单的说就是两个人轮流抽牌,每个人都可以从头抽或者从尾抽,抽到了就加相应的分数,最后看谁的分高。
解题思路:
用了递归。。
bool PredictTheWinner(vector<int>& nums) {
return myFunc(nums, 0, nums.size()-1) >= 0;
}
int myFunc(vector<int>& nums, int start, int end) {
if (start == end)
return nums[start];
int i = nums[start] - myFunc(nums, start+1, end);
int j = nums[end] - myFunc(nums, start, end-1);
return i > j ? i : j;
}
leetcode-23-DynamicProgramming-1的更多相关文章
- [LeetCode] 23. Merge k Sorted Lists 合并k个有序链表
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...
- LeetCode 23. 合并K个排序链表(Merge Two Sorted Lists)
23. 合并K个排序链表 23. Merge k Sorted Lists 题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. LeetCode23. Merge k S ...
- Java实现 LeetCode 23 合并K个排序链表
23. 合并K个排序链表 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输 ...
- [leetcode 23]Merge k Sorted Lists
1 题目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexi ...
- [LeetCode] 23. Merge k Sorted Lists ☆☆☆☆☆
转载:https://leetcode.windliang.cc/leetCode-23-Merge-k-Sorted-Lists.html 描述 Merge k sorted linked list ...
- 蜗牛慢慢爬 LeetCode 23. Merge k Sorted Lists [Difficulty: Hard]
题目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity ...
- LeetCode 23 Merge k Sorted Lists(合并k个有序链表)
题目链接: https://leetcode.com/problems/merge-k-sorted-lists/?tab=Description Problem: 给出k个有序的list, 将其进行 ...
- [LeetCode]23. 合并K个排序链表(优先队列;分治待做)
题目 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1 ...
- Java [leetcode 23]Merge k Sorted Lists
题目描述: Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complex ...
- LeetCode(23)-Implement Queue using Stacks
题目: Implement the following operations of a queue using stacks. push(x) -- Push element x to the bac ...
随机推荐
- Hive进阶_Hive的客户端操作
启动远程客户端 # hive --service hiveserver2获取连接-〉创建运行环境-〉执行HQL-〉处理结果-〉释放资源 工具类 package demo.utils; import j ...
- spring boot 事务
spring事务:默认自动提交只读:@Transactional(readOnly = true)读写:@Transactional(),因为等同于@Transactional(readOnly = ...
- ExpandoObject的使用
IDictionary<string, object> obj = new System.Dynamic.ExpandoObject(); obj.Add(); dynamic obj2 ...
- Spark Mllib里如何对决策树二元分类和决策树多元分类的分类数目numClasses控制(图文详解)
不多说,直接上干货! 决策树二元分类的分类数目numClasses控制 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的第13章 使用决策树二元分类算法来预测分类Stumble ...
- java join 方法的使用
在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程结束之前结束.这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据 ...
- vuex填坑记录
vuex是需要等待页面加载完成后才会更新的,如果页面点击刷新有用到vuex的地方,那么vuex会保持旧的数据,等刷新完成后vuex的数据才会重置,所以要在页面加载后再调用vuex的数据才是正确的,如果 ...
- Dubbo 使用rest协议发布http服务
演示用GitHub地址:https://github.com/suyin58/dubbo-rest-example 1 Dubbo_rest介绍 Dubbo自2.6.0版本后,合并了dub ...
- php 判断字符串中是否包含另一个字符串 strpos
strpos (PHP 4, PHP 5, PHP 7) strpos — 查找字符串首次出现的位置 说明 strpos ( string $haystack , $needle [, int $o ...
- layout_weight属性
layout_weight 某个控件text多行,第一行对齐,baselineAligned = "false" 可使控件对齐 weight 计算规则 剩余尺寸=父布局尺寸-子布局 ...
- apple-touch-icon-precomposed
<link rel="apple-touch-icon-precomposed" href=""> apple-touch-icon-precomp ...