从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。
2017-01-15 11:51
232 查看
提示:双端 LIS 问题,用 DP 的思想可解。
#include <iostream> using namespace std; void printArray(int* arr, int len) { for (int i = 0; i < len; ++i) { cout << arr[i] << ' '; } cout << endl; } int binaryFind(int* lis, int target, int end) { int low = 0; int high = end; while (low <= high) { int mid = (low + high) / 2; if (target > lis[mid]) { low = mid + 1; } else if (target < lis[mid]) { high = mid - 1; } else { return mid; } } return low; } /*B[i]是从左到右的,0~i个数之间满足递增的数字个数; * C[i]为从右到左的,n- 1 ~ i个数之间满足递增的数字个数 * 最后结果为n - max{B[i] + C[i] - 1} * */ int doubleEndLIS(int* arr, int len) { int* dp1 = new int[len]; int* dp2 = new int[len]; int* lis = new int[len]; memset(dp1, 0, sizeof(int) * (len)); memset(dp2, 0, sizeof(int) * (len)); memset(lis, 0, sizeof(int) * (len)); dp1[0] = 1; lis[0] = arr[0]; int maxlen = 1; for (int i = 1; i < len; ++i) { int pos = binaryFind(lis, arr[i], maxlen - 1); lis[pos] = arr[i]; dp1[i] = pos + 1; if (pos >= maxlen) { maxlen++; } } memset(lis, 0, sizeof(int) * len); lis[0] = arr[len - 1]; dp2[len - 1] = 1; maxlen = 1; for (int i = len - 2; i >= 0; --i) { int pos = binaryFind(lis, arr[i], maxlen - 1); lis[pos] = arr[i]; dp2[i] = pos + 1; if (pos >= maxlen) { maxlen++; } } // printArray(dp1, len); // printArray(dp2, len); int mid = 0; int result = 0; for (int i = 0; i < len; ++i) { result = max(result, dp1[i] + dp2[i]); if (result == dp1[i] + dp2[i]) mid = i; } result--; //还原子序列 lis = new int[result]; memset(lis, 0, result * sizeof(int)); int curLen = dp1[mid]; for (int i = mid; i >= 0; --i) { if (dp1[i] == curLen) { lis[curLen - 1] = arr[i]; curLen--; if (curLen == 0) { break; } } } //结果集下标 int index = dp1[mid]; curLen = dp2[mid] - 1; for (int i = mid + 1; i < len; ++i) { if (dp2[i] == curLen) { lis[index++] = arr[i]; curLen--; if (curLen == 0) { break; } } } printArray(lis, result); result = len - result; return result; }
相关文章推荐
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的(网易)。 题目描述:
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的(网易)。
- 从一列数中筛除尽可能少的数,使得从左往右看这些数是从小到大再从大到小
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的
- 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的
- 不选择使用Lucene的6大原因(转载) - Hubble.net 将尽可能解决这些问题
- 算法:给定两个已从小到大排好序的整型数组arrA和arrB,将两个数组合并成arrC,使得arrC也要按从小到大的顺序排好序
- 【FOJ2210 11月月赛F】【DFS or 拓扑排序】攻占计划 n个点m条边DAG破坏一个点使得不可达点数尽可能多
- 【2015ZUFE新生赛网络同步赛G】【贪心】贪心的小猫咪 不含0的字符串删除一位使得数值尽可能大
- 给定一个实数数组,按序排列(从小到大),从数组从找出若干个数,使得这若干个数的和与M最为接近,描述一个算法,并给出算法的复杂度。
- 找词”游戏是在美国流行的一种游戏,它要求游戏者从一张填满字母的正方形表中,找出包含在一个给定集合中的所有词。这些词可以竖着读(向上或向下)、横着读(从左或从右),或者沿45度对角线斜着读。
- 给定一个实数数组,按序排列(从小到大),从数组从找出若干个数,使得这若干个数的和与M最为接近,描述一个算法,并给出算法的复杂度。
- 要求写一个程序,返回最少的操作数,使得源串进行这些操作后等于目标串。源串和目标串长度都小于2000。
- UVA10160在一个图中选择几个点,使得这些点加上相邻的点为这个图的顶点集
- 【2015-2016 ACM-ICPC Pacific Northwest Regional Contest (Div 1)E】【水题 贪心】Excellence n个数两两组合使得最小和尽可能大
- 不选择使用Lucene的6大原因(转载) - Hubble.net 将尽可能解决这些问题
- 每天学习一算法系列(5)(已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集)