# 手撕数组

### 【面试题03：二维数组中的查找】Search a 2D Matrix II

class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty())
return false;
int row = matrix.size();
int col = matrix[0].size();
int i = 0, j = col-1;
while(i<row && j>=0){
if(matrix[i][j] == target)
return true;
while(j>=0 && matrix[i][j]>target)
j--;
while(i<row && matrix[i][j]<target)
i++;
}
return false;
}
};

### 【面试题08：旋转数组的最小数字】Find Minimum in Rotated Sorted Array II

class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.empty()) return -1;
int begin = 0;
int end = nums.size()-1;
if(nums[begin]<nums[end]) return nums[begin];//特殊情况：旋转数组本身为排序数组
while(begin <= end){
if(begin == end || (begin+1 == end)) return nums[end];
int middle = (begin+end)/2;
if(nums[middle]==nums[begin] && nums[middle]==nums[end])
//特定情况，只能采用顺序查找了。如[10111]
return sequenceFindMin(nums,begin,end);
if(nums[middle]>=nums[begin])
begin = middle;
if(nums[middle]<=nums[end])
end = middle;
}
}
int sequenceFindMin(vector<int>& nums,int begin,int end){
int min = nums[begin];
for(int i = begin+1;i <= end;i++){
if(min>nums[i]) min = nums[i];
}
return min;
}
};

### 【面试题11：数值的整数次方】Pow(x, n)

class Solution {
public:
double myPow(double x, int n) {
if(x == 0.0) return 0.0;
if(n == 0) return 1.0;
if(n == 1) return x;
unsigned int absn = n<0? -n: n;
double result = myPow(x,absn>>1);
result *= result;
if(n%2) result *= x;
return n<0? 1.0/result:result;
}
};

### 【面试题12：打印1 到最大的n 位数】

void printtomax2(int n)
{
if (n <= 0) return;
char *number = new char[n + 1];
number[n] = '\0';
printnumber(number, n, -1);//调用递归方法
}

void printnumber(char *number, int n, int index)
{//判断最后一位数字是否已经赋值，是则打印
if (index == n - 1){
Print(number);
return;
}
//否则递归赋值，直到到达最后一位
//从下一位开始，0-9依次赋值
for (int i = 0; i<10; i++){
number[index + 1] = '0' + i;
printnumber(number, n, index + 1);
}
}

//打印number中存的数字
void Print(char * number)
{
int length = strlen(number);
int i = 0;
while (i < length && number[i] != '0')
i++;
while (i++ < length)
cout << number[i];
cout << "   ";
}

### 【面试题14：调整数组顺序使奇数位于偶数前面】

void ReOrderOddEven_2(int *pdata,unsigned int length){
if(pdata==NULL || length<=0)
return;
int *pBegin=pdata;
int *pEnd=pdata+length-1;

while(pBegin<pEnd){
while(pBegin<pEnd && (*pBegin&0x1)!=0)
pBegin++;
while(pBegin<pEnd && (*pEnd&0x1)==0)
pEnd--;
if(pBegin<pEnd){
int tmp=*pBegin;
*pBegin=*pEnd;
*pEnd=tmp;
}
}
}

### 【面试题20：顺时针打印矩阵】Spiral Matrix

class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix){
vector<int>printVector;
if(matrix.empty()) return printVector;
int rows = matrix.size();
int cols = matrix[0].size();
int start = 0;
while(cols>start*2  && rows > start*2){
int endX = cols - 1 - start;
int endY = rows - 1 - start;
for(int i = start;i<=endX ;i++){
printVector.push_back(matrix[start][i]);
}//from right to left
if(endY>start){
for(int i = start+1; i<= endY ;i++)
printVector.push_back(matrix[i][endX]);
}//from up to down
if(endX>start && start< endY){
for(int i = endX-1; i>= start; i--)
printVector.push_back(matrix[endY][i]);
}//from left to right:
if(endX>start && endY>start+1){
for(int i = endY-1; i> start; i--)
printVector.push_back(matrix[i][start]);
}//from down to up
start++;
}
return printVector;
}
};

### 【面试题29：数组中出现次数超过一半的数字】Majority Element

class Solution {
public:
int majorityElement(vector<int>& nums) {
int index = Partition(nums,0,nums.size()-1);
int middle = nums.size()/2;
while(index != middle)
index = index>middle? Partition(nums,0,index-1):Partition(nums,index+1,nums.size()-1);
return nums[middle];
}
int Partition(vector<int> &number,int begin, int end){
int random = number[begin];
while(begin<end){
while(begin<end && number[end]>=random)
end--;
number[begin] = number[end];
while(begin<end && number[begin]<=random)
begin++;
number[end] = number[begin];
}
number[begin] = random;
return begin;
}
//利用map统计元素个数
/*int majorityElement(vector<int>& nums) {
map<int,int>mapping;
int len = nums.size();
for(int i = 0; i < len; i++){
if(++mapping[nums[i]]>(len/2)) return nums[i];
}
}*/
};

### 【面试题30：最小的k个数】

void GetLeastKNum(int *input,int n,int *output,int k)
{
if(input==NULL || n<=0 || k<=0) return;
int start=0;
int end=n-1;
int index=Partition(input,start,end);
while(index!=k-1)
index=index<k-1 ? Partition(input,index+1,end) : Partition(input,start,index-1);
for(int i=0;i<k;i++)
output[i]=input[i];
//其中，output[k-1]就是第k小的数
}

### 【面试题64：数据流中的中位数】

（1）make_heap()构造堆
void make_heap(first_pointer,end_pointer,compare_function);

（2）push_heap()添加元素到堆
void push_heap(first_pointer,end_pointer,compare_function);

（3）pop_heap()从堆中移出元素
void pop_heap(first_pointer,end_pointer,compare_function);

（4）sort_heap()对整个堆排序

class Solution {
public:
void Insert(int num){
if(((max.size()+min.size())%2) == 0){
if(max.size()&& num<max[0]){
max.push_back(num);
push_heap(max.begin(),max.end(),less<int>());// 调整最大堆
num = max[0];
pop_heap(max.begin(),max.end(),less<int>());
max.pop_back();//在容器中删除
}
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
}
else{
if(min.size()>0 && num>min[0]){
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
num = min[0];
pop_heap(min.begin(),min.end(),greater<int>());
min.pop_back();
}
max.push_back(num);
push_heap(max.begin(),max.end(),less<int>());
}
}

double GetMedian()
{
if(((max.size()+min.size())&1) == 0)
return (max[0]+min[0])/2.0;
else
return min[0];
}
private:
vector<int>min;
vector<int>max;
};

### 【面试题31：连续子数组的最大和】

#include<limits.h>//INT_MAX与INT_MIN的头文件
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.size() == 0) return 0;
int sum = 0;
int max = INT_MIN;//0x80000000;
//给int类型赋值的话，0X7FFFFFFF代表最大值，0X80000000代表最小值
//NT_MAX 代表最大值， INT_MIN 代表最小值
for(int i = 0;i<array.size();i++){
if(sum<=0) sum = array[i];
else sum += array[i];
if(sum>max) max = sum;
}
return max;
}
//动态规划思想，sum[i] = sum[i-1]<=0 ? array[i]:sum[i-1]+array[i];
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.size() == 0) return 0;
int max = INT_MIN;
int sum[array.size()];
sum[0] = array[0];
for(int i = 1;i<array.size();i++){
if(sum[i-1]<=0) sum[i] = array[i];
else sum[i] = sum[i-1]+array[i];
if(sum[i]>max) max = sum[i];
}
return max;
}
};

### 【面试题44：数字序列中某一位的数字】

class Solution {
public:
int findNthDigit(int n) {
if(n <= 0) return 0;
if(n>std::pow(2,31)) return 0;
int bit = 1;
while(n>bit*9*std::pow(10,bit-1)){
n -= bit*9*std::pow(10,bit-1);
bit++;
}//第一个定位，并更新n
int existnumber = std::pow(10,bit-1)+ (n-1)/bit;//第二个定位
}
}

### 【面试题47：礼物的最大价值】Minimum Path Sum

Note: You can only move either down or right at any point in time.

#include<limits.h>
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
if(grid.size() == 0) return 0;
int minSum[grid.size()][grid[0].size()];
/*申请动态数组：
int** minSum = new int* [grid.size()];
for (int i=0; i<grid.size(); i++)
minSum[i]= new int[grid[0].size()];
//释放内存：
for (int i=0; i<grid.size(); i++)
delete[] minSum[i];
delete[] minSum;*/
for (int i=0; i<grid.size(); i++){
for(int j = 0;j<grid[0].size();j++){
if(i== 0&&j == 0) minSum[0][0] = grid[0][0];
else{
int right = i>0 ?minSum[i-1][j]:INT_MAX;
int down = j>0 ? minSum[i][j-1]:INT_MAX;
minSum[i][j] = std::min(right,down)+grid[i][j];
}
}
}
return minSum[grid.size()-1][grid[0].size()-1];
}
};

### 【面试题34：丑数】

class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index<=0) return 0;
int UglyNumber[index];
UglyNumber[0] = 1;
int *pMultiply2 = UglyNumber;
int *pMultiply3 = UglyNumber;
int *pMultiply5 = UglyNumber;
int curIndex = 1;
while(curIndex<index){
UglyNumber[curIndex] = Min(*pMultiply2*2,*pMultiply3*3,*pMultiply5*5);
while(*pMultiply2*2 <= UglyNumber[curIndex])
pMultiply2++;
while(*pMultiply3*3 <= UglyNumber[curIndex])
pMultiply3++;
while(*pMultiply5*5 <= UglyNumber[curIndex])
pMultiply5++;
curIndex++;
}
return UglyNumber[index-1];
}
int Min(int num1,int num2,int num3) {
int min = std::min(num1,num2);
return std::min(min,num3);
}
};

### 【面试题38：在排序数组中查找数字-数字在排序数组中出现的次数】Find First and Last Position of Element in Sorted Array

class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int>position;
if(nums.size() != 0){
int firstPos = SearchFirstValue(nums,target,0,nums.size()-1);
int lastPos = SearchLastValue(nums,target,0,nums.size()-1);
position.push_back(firstPos);
position.push_back(lastPos);
}
else{
position.push_back(-1);
position.push_back(-1);
}
return position;
}
int SearchFirstValue(vector<int>& nums, int target, int begin, int end) {
if(begin> end) return -1;
int middle = (begin+end)/2;
if(nums[middle] == target){
if((middle>=1 && nums[middle-1] != target) || middle == 0 )
return middle;
end = middle-1;
}
else if(nums[middle] > target)
end = middle-1;
else
begin = middle+1;
return SearchFirstValue(nums,target,begin,end);
}
int SearchLastValue(vector<int>& nums, int target, int begin, int end) {
if(begin> end) return -1;
int middle = (begin+end)/2;
if(nums[middle] == target){
if((middle<nums.size()-1 && nums[middle+1] != target) || middle == nums.size()-1)
return middle;
begin = middle+1;
}
else if(nums[middle] < target)
begin = middle+1;
else
end = middle-1;
return SearchLastValue(nums,target,begin,end);
}
};

### 【面试题57：和为s的数字】

class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int behind = array.size()-1;
int temp = array[ahead] + array[behind];
if( temp == sum)
else if(temp < sum)
else
behind--;
}
return {};
}

vector<vector<int> > FindContinuousSequence(int sum) {
if(sum<3) return {};
int small = 1;
int big = 2;
vector<vector<int>>Result;
while(big <= (sum+1)/2){//big+(big-1)<=sum,至少有两个数
int temp = (small+big)*(big-small+1)/2;
if(temp == sum){
vector<int>result;
for(int i=small; i<=big; i++)
result.push_back(i);
Result.push_back(result);
big++;
}
else if(temp < sum)
big++;
else
small++;
}
return Result;
}
};

### 【面试题63：股票的最大利润】Best Time to Buy and Sell Stock

class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size() <= 1) return 0;
int min = prices[0];
int maxProfit = 0;
for(int i=1; i<prices.size(); i++){
if(prices[i]<min)
min = prices[i];
int profitDiff = prices[i] - min;
if(profitDiff>maxProfit)
maxProfit = profitDiff;
}
return maxProfit;
}
//多次交易的最大利润。
int maxProfit(vector<int>& prices) {
int maxProfit = 0;
for(int i=1; i<prices.size();i++)
maxProfit += std::max(0, prices[i]-prices[i-1]);
return maxProfit;
}
};

### 网易-个人所得税

int sal2tax(int salary) {
salary -= 2000;//计算应扣税部分
double tax = 0;
double sal[][2] = {
{0, 0.05},
{500, 0.1},
{2000, 0.15},
{5000, 0.2},
{20000, 0.25},
{40000, 0.3},
{60000, 0.35},
{80000, 0.4},
{100000, 0.45}
};
for(int i = 0; i < 8; ++i) {
if(salary < sal[i][0]) break;
tax += (salary> sal[i + 1][0]) ? (sal[i + 1][0] - sal[i][0]) : (salary - sal[i][0])) * sal[i][1];
}
return int(tax+0.5);
}
int tax2sal(int tax){
int sal_h = 80000;
int sal_l = 0;
while(sal_h>sal_l){
int mid = (sal_h + sal_l)/2;
if(sal2tax(mid) == tax)
return mid;
if(sal2tax(mid)>tax)
sal_h = mid-1;
else
sal_l = mid+1;
}
return -1；
}

### 好未来-求和

##### 输出描述:

//递归遍历框架：打印所有1到n的排列组合。
void resursive(vector<int>&combine,int num) {
//设置遍历过程的操作，可以是全部打印，可以是特定条件下的打印
for (int j = 0; j < combine.size(); j++)
cout << combine[j];
cout << endl;
//以树为例
for (int i = num; i < 4; i++) {
combine.push_back(i); // 保存父结点
resursive(combine,i+1); //遍历该父节点的的子树。
combine.pop_back();//弹出结点，遍历该父节点的其他兄弟树。
}
}

int main() {
vector<int>combine;
resursive(combine,1);

5 5

1 4
2 3
5

#include<iostream>
#include<vector>

using namespace std;

void traverse(vector<int>&combine,int num, int n,int m){
if(m == 0){
for(int j=0; j<combine.size();j++)
j==0 ? cout<<combine[j] : cout<<' '<<combine[j];
cout<<endl;
}
for(int i=num; i<=n && i<=m; i++){
combine.push_back(i);
traverse(combine,i+1,n,m-i);
combine.pop_back();
}
}

int main(){
int n,m;
vector<int>combine;
while(cin>>n>>m){
traverse(combine,1,n,m);
}
return 0;
}

### 好未来-n个数里最小的k个

##### 注意: 题目要求排序打印。1）直接sort排序输出，2）分治找出k个数，然后排序输出

3 9 6 8 -10 7 -11 19 30 12 23 5

-11 -10 3 6 7

#include<iostream>
#include<vector>
#include <algorithm>

using namespace std;

int Partition(vector<int> &number,int begin, int end){
int random = number[begin];
while(begin<end){
while(begin<end && number[end]>=random){
end--;
}
number[begin] = number[end];
while(begin<end && number[begin]<=random){
begin++;
}
number[end] = number[begin];
}
number[begin] = random;
return begin;
}
int main(){
int input;
vector<int>number;//获取符号，不会忽略换位符\n，空格之类
while(cin>>input){
number.push_back(input);
}//这样输入，题目也能运行
int k = number.back();
number.pop_back();
int index = Partition(number,0, number.size()-1);
while(index != k-1){
index = index > k-1 ? Partition(number,0,index-1)
:Partition(number,index+1,number.size()-1);
}
//直接用algorithm中的sort
sort(number.begin(),number.begin()+k);
for(int i=0; i<k; i++){
i<k-1 ? cout<<number[i]<<' ': cout<<number[i]<<endl;
}
}

#include <algorithm>
bool great)(int a,int b)
return a>b;
bool les(node a, node b)
return a.val > b.val;
sort(vec.begin(),vec.end(),great);   //升序，默认
sort(vec.begin(), vec.end(),les); //降序

### 美团-拼凑钱币

sum = x1 * V1 + x2 * V2 + ... + xi * Vi ,xi可取0，1...K=sum/Vi。即

#include<iostream>
using namespace std;
int main() {
int coins[6] = {1,5,10,20,50,100};
int n;
while (cin >> n) {
long dp[6][n+1];
for(int i=0; i<6; i++){
for(int j=0;j<=n; j++)
dp[i][j] = 0;
}  //初始化dp
for(int j=0;j<=n;j++)
dp[0][j]=1;//只使用第一个钱币1时，组合数都是1.
for(int i=1;i<6;i++){
for(int j=1;j<=n;j++){
for(int k=0; k<=j/coins[i]; k++)
dp[i][j] += dp[i-1][j - k*coins[i]];
}
}
cout << dp[5][n] << endl;
}
return 0;
}