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 ...
随机推荐
- (转)io优化
原文:http://blog.csdn.net/gzh0222/article/details/9227393 1.系统学习 IO性能对于一个系统的影响是至关重要的.一个系统经过多项优化以后,瓶颈往往 ...
- ASPECTJ 注解。。。
public interface ISomeService { public void doSome(); public String dade(); } public class SomeServi ...
- vue2.0:(八-2)、外卖App弹窗部分sticky footer
什么是sticky-footer ? 如果页面内容不够长的时候,页脚块粘贴在视窗底部,如果内容足够长时,页脚块会被内容向下推送.那具体要怎么做呢?下面以外卖App为例: 第一种方法:这个自己用过,是好 ...
- div嵌套时,子元素设置margin-top失效问题
这是因为父元素的padding设置为0时所产生的bug,它自动将margin-top提升到了父元素上,所以此时我们所设置的margin-top自动就到父元素上了,解决方案: 1.给父元素添加一个pad ...
- Windows系统下查看文件编码类型
这是一个程序员的最基本的技能,原谅我到现在才去了解 以前只知道window操作系统下文件大部分默认编码是ANSI,中文版是GBK编码 如果想要查看或者修改文件编码的话有两种方式 一:用记事本打开文件, ...
- 51nod 1101 换零钱
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 10 20 50 100元. ...
- 关于日志造成的频繁的IO
记录日志可能消耗大量的IO [Q] 每次写入都是一个IO操作 即使是同一个文件 两次写入也要打开两次IO操作 [F] 设想有这样一个扩展 把php中要记录的日志 用文件名 和 内容的方式记录在内存中 ...
- RAC数据库后台进程介绍
在RAC数据库上会比单实例数据库多一些进程,这些进程是RAC特有的,为了实现集群数据库功能而设置的. 10g RAC特有进程:$ ps -ef|grep ora_oracle 4721 ...
- UVA 11992 Fast Matrix Operations (降维)
题意:对一个矩阵进行子矩阵操作. 元素最多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作. 一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测 ...
- php有哪些优化技巧
1. echo 比 print 快.2. 使用echo的多重参数代替字符串连接.3. 在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替.4. 对global变 ...