1.动态规划
Q:接下来,我们就可以开篇的问题了,什么样的题适合用动态规划?
A:一般,动态规划有以下几种分类:
- 最值型动态规划,比如求最大,最小值是多少
- 计数型动态规划,比如换硬币,有多少种换法
- 坐标型动态规划,比如在m*n矩阵求最值型,计数型,一般是二维矩阵
- 区间型动态规划,比如在区间中求最值
和为S的两个数字 !!!
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
// 因为数组是有序的,所以可以用双指针,指向数组的首尾,具体步骤如下:
// 1.初始化:指针i指向数组首, 指针j指向数组尾部
// 2. 如果arr[i] + arr[j] == sum , 说明是可能解
// 3. 否则如果arr[i] + arr[j] > sum, 说明和太大,所以--j
// 4. 否则如果arr[i] + arr[j] < sum, 说明和太小,所以++i
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
if(array.empty()) return vector<int>(); //vector<int>()这个表示空??????
int i=0,j=array.size();
int tmp=INT_MAX;
pair<int,int> ret; //???为什么要有这个
while(i<j)
{
if(array[i]+array[j-1]==sum){
if(array[i]*array[j-1]<tmp){
tmp=array[i]*array[j-1];
ret={i,j-1};
}
++i,--j;
}else if(array[i]+array[j-1]>sum){
--j;
}else{
++i;
}
}
if(ret.first == ret.second) return vector<int>();
return vector<int>({array[ret.first],array[ret.second]});
}
};
二分法
题目描述:统计一个数字在升序数组中出现的次数。!!!!
输入:[1,2,3,3,3,3,4,5],3
输出:4
class Solution {
public:
int GetNumberOfK(vector<int> nums ,int target) {
int lbound = 0, rbound = 0;
// 寻找上界
int l = 0, r = nums.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] < target) {
l = mid + 1;
}
else {
r = mid;
}
}
lbound = l;
// 寻找下界
l = 0, r = nums.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] <= target) {
l = mid + 1;
}
else {
r = mid;
}
}
rbound = l;
return rbound - lbound;
}
};
//还可以用stl里面的upper_bound()和lower_bound()接口
//class Solution {
//public:
// int GetNumberOfK(vector<int> nums ,int target) {
// return upper_bound(nums.begin(), nums.end(), target) - //lower_bound(nums.begin(), nums.end(), target);
// }
//};
题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
输入:[3,4,5,1,2]
输出:1
class Solution {
public:
int minNumberInRotateArray(vector<int> Arr) {
// sort(rotateArray.begin(),rotateArray.end());
// if(rotateArray[0]<=0) return 0;
// return rotateArray[0];
//这个解法太智障了。。。。
int left=0,right=Arr.size()-1;
while(left<right){
int mid=left+(right-left)/2;
if(Arr[mid]<Arr[right]){//后半部分是顺序的
right=mid;
}
else if(Arr[mid]>Arr[right]){//前半部分是顺序的
left=mid+1;
}else{
right--;
}
}
return Arr[right];
}
};
树
给定一棵二叉搜索树,请找出其中的第k小的结点。
//非递归版中序遍历,可以利用栈来模拟递归遍历,首先根入栈,然后令根节点的左孩子不断入栈直到空,
//弹出栈顶,令其右孩子入栈,重复以上操作,直到遍历结束或者访问第k个节点为止。
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(!pRoot) return nullptr;
stack<TreeNode *> res;
TreeNode *p=pRoot;
while(!res.empty() || p){
while(p){
res.push(p);
p=p->left;
}
TreeNode *node=res.top();
res.pop();
if((--k)==0) return node;
p=node->right;
}
return nullptr;
}
};