求数组中最长递增子序列,数组分割,数组循环移位,区间重合判断
2017-03-31 22:45
190 查看
求数组中最长递增子序列
编程之美2.16注意,所谓的递增子序列不一定是连续的
只要满足递增性即可。
方法:动态规划思想。
用dp[i]表示到i为止,最长的递增序列长度。(可能包含i,也可能不包含i)
那么dp[i+1]就是判断A[i+1]能否加上,即
dp[i+1]=max(dp[0~i]+A[0~i]
int calculong(int *A, int n) { int *dp = new int ; dp[0] = 1; for (int i = 1;i < n;i++) { int tmp = INT_MIN; for (int j = 0;j < i;j++) { if (A[i] > A[j] && tmp < dp[j] + 1) tmp = dp[j] + 1; else if (tmp<dp[j]) tmp = dp[j]; } dp[i] = max(1, tmp); } int res = INT_MIN; for (int i = 0;i < n;i++) if (res < dp[i]) res = dp[i]; return res; }
数组分割
对于一个无序数组,长度2n,如何把这个数组分割为两个长度为n的数组,使其和最接近。先解决这样一个问题:
//1. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为两个子数组,子数组的元素个数不限,并使两个子数组之和最接近。
#define MAXN 101 #define MAXSUM 1000 void ArrayDivision(int *A, int n) { bool dp[MAXN][MAXSUM];// dp[k][s]表示从前k个数中取任意个数的数,且这些数之和为s的取法是否存在 memset(dp, 0, sizeof(dp)); dp[0][0] = true; int i, sum=0; for (i = 0; i <= 2 * n-1; i++) sum += A[i]; cout << sum << endl; // 外阶段k1表示第k1个数 for (int k1 = 1;k1 <= 2 * n;k1++) for (int s = 1;s <= sum / 2;s++) { // 有两个决策包含或不包含元素k1 if (dp[k1 - 1][s]) dp[k1][s] = true; if (s >= A[k1-1] && dp[k1 - 1][s - A[k1-1]]) dp[k1][s] = true; } for (int s = sum / 2;s >= 1;s--) { if (dp[2 * n][s]) { cout << s << endl; break; } } }
再回到原问题:
//2. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组之和最接近。 void ArrayDivision2(int *A, int n) { bool dp[MAXN][MAXSUM];// dp[k][s]表示是否可以找到k个数,其和为s memset(dp, 0, sizeof(dp)); dp[0][0] = true; int i, sum = 0; for (i = 0; i <= 2 * n - 1; i++) sum += A[i]; cout << sum << endl; // 外阶段k1表示第k1个数 for (int k1 = 1;k1 <= 2 * n;k1++) for (int k2 = min(k1, n);k2 >= 1;k2--) for (int s = 1;s <= sum / 2;s++) { if (s >= A[k1 - 1] && dp[k2 - 1][s - A[k1 - 1]])//因为每次更新k1,我们就要判断新增加的A[k1]是否会影响前面的dp[0~k2][s]的值,所以只需更新加上A[k1]后影响的值就行了。 dp[k2][s] = true; } for (int s = sum / 2;s >= 1;s--) { if (dp [s]) { cout << s << endl; break; } } }
第二种不太好想,看注释!
注意两个dp[k][s]表示的意思是不一样的。
数组循环移位
对数组循环向右移动k位求解思路:
逆序前n-k个
逆序后k个
然后对整个逆序
区间重合判断
类似于阿里的一个面试题。就是给你一个target线段,判断它是否被已给出的一些线段所包含。
思路:
先排序,然后遍历排序好的线段,对target的x进行更新判断。画图比划一下即可。
struct line { int x; int y; }; void swap(line &x, line &y) { line temp=x; x = y; y = temp; } void QuickSort(line *A,int left, int right) { if (left < right) { int lo = left, hi = right; line key = A[lo]; while (lo < hi) { while (lo<hi&&A[hi].x >= key.x) hi--; swap(A[lo], A[hi]); while (lo < hi&&A[lo].x <= key.x) lo++; swap(A[lo], A[hi]); } QuickSort(A, left, lo-1); QuickSort(A, lo+1, right); } } bool IsExist(line*A, int n,line target) { QuickSort(A,0,n-1); for (int i = 0;i < n;i++) { if (target.x >= target.y) return true; if (A[i].y < target.x) { continue; } else { if (A[i].x > target.x) continue; else target.x= A[i].y; } } return false; }
相关文章推荐
- 找工作知识储备(2)---数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 最大子数组之和、最大子数组之积、最长递增子序列求法
- ] 找工作知识储备(2)---数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- hdoj 3308 LCIS 【线段树单点更新 + 区间合并】【求解最长递增序列 的长度】
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和
- 求数组中最长递增子序列的长度
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和
- 链表逆序(递归&非递归)/倒序输出链表值/用一个递增序列构建平衡二叉搜索树/用递归的方法判断数组是不是升(降)序排列
- 求数组中最长递增子序列的长度
- O(n)时间找出无序数组中最长的连续递增序列
- 求数组中最长递增子序列的长度
- 求数组中最长递增子序列的长度
- 数组最长递增序列
- 2.16 求数组中最长的递增子序列
- 编程之美-求数组中最长递增子序列(LIS)方法整理
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和
- 求解数组中最长递增自序列