主要是记录在刷题过程的一些题目
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<unordered_map>
#include<math.h>
#include<algorithm>
#include <set>
#include <map>
#include<string>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
//返回排好序的数组中和为指定数的下标
vector<int> twoSum(vector<int>& numbers, int target) {
int size = numbers.size();
vector<int> res;
int i = 0, j = size - 1;
while (i != j) {
if (numbers[i] + numbers[j] == target) {
res.push_back(i + 1);
res.push_back(j + 1);
return res;
}
else if (numbers[i] + numbers[j]>target) {
j--;
}
else {
i++;
}
}
return res;
}
//返回无序数组中和为指定数的下标
vector<int> twoSumNoOrder(vector<int>& nums, int target) {
// int size=nums.size();
// vector<int> res;
// int i=0,j=size-1;
// for(auto i=0;i<size;++i){
// for(auto j=i+1;j<size;++j){
// if(nums[i]+nums[j]==target){
// res.push_back(i);
// res.push_back(j);
// return res;
// }
// }
// }
// return res;
unordered_map<int, int>hash;
vector<int> res;
int toBeFound = 0, i = 0;
for (auto num : nums) {//
toBeFound = target - num;
if (hash.find(toBeFound) != hash.end()) {
res.push_back(hash[toBeFound]);
res.push_back(i);
return res;
}
hash[num] = i++;
}
return res;
}
//统计占有一半以上的数字(假设总是存在,不存在的话找到这个数字再遍历一遍看是否≥n/2即可
int majorityElement(vector<int>& nums) {
int major, counts = 0, n = nums.size();
for (int i = 0; i < n; i++) {
if (!counts) {
major = nums[i];
counts = 1;
}
else counts += (nums[i] == major) ? 1 : -1;
}
return major;
}
//右移k位1234567-3 ---》5671234
void rotate(vector<int>& nums, int k) {
if (k == 0)return;
int tmp = 0, size = nums.size();
vector<int>::iterator it = nums.begin();
for (int i = 0; i<k; ++i) {
tmp = nums[size - 1];
nums.erase(it + size - 1);
nums.insert(nums.begin(), tmp);
}
}
void rotateArr(int arr[], int n, int k) {
if (!arr || n <= 0 || k <= 0)return;
k %= n;
reverse(arr, arr + n);
reverse(arr, arr + k);
reverse(arr+k, arr+n );
}
void rotateUseNSpace(int nums[], int n, int k)
{
if ((n == 0) || (k <= 0))
{
return;
}
// Make a copy of nums
vector<int> numsCopy(n);
for (int i = 0; i < n; i++)
{
numsCopy[i] = nums[i];
}
// Rotate the elements.
for (int i = 0; i < n; i++)
{
nums[(i + k) % n] = numsCopy[i];
}
}
//相邻k个数的最大平均数
double findMaxAverage(vector<int>& nums, int k) {
double res = INT_MIN, nSum = 0;
int size = nums.size();
for (int i = 0; i<size; ++i) {
if (i<k) {
nSum += nums[i];
}
else {
res = max(res, nSum);
nSum += nums[i] - nums[i - k];
}
}
res = max(res, nSum);
return res / k;
}
//数组去重
int removeDuplicates(vector<int>& nums) {
int i = !nums.empty();
for (auto val : nums) {
if (val>nums[i - 1]) {
nums[i++] = val;
}
}
return i;
}
//数组去除指定数字
int removeElement(vector<int>& nums, int val) {
int i = 0;
for (auto num : nums)if (val != num)nums[i++] = num;
return i;
}
//三个数相乘最大,排序后最大的三个数相乘或者最小的两个数和最大的数相乘(考虑有负数的情况)
//或者遍历一遍寻找最大的三个数和最小的两个数
int maximumProduct(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
int temp1 = nums[n - 1] * nums[n - 2] * nums[n - 3];
int temp2 = nums[0] * nums[1] * nums[n - 1];
return temp1>temp2 ? temp1 : temp2;
}
int maximumProduct2(vector<int>& nums) {
int max1 = INT_MIN, max2 = INT_MIN, max3 = INT_MIN, min1 = INT_MAX, min2 = INT_MAX;
for (auto val : nums) {
if (val > max1) {
max3 = max2;
max2 = max1;
max1 = val;
}
else if(val>max2){
max3 = max2;
max2 = val;
}
else if (val > max3) {
max3 = val;
}
if (val < min1) {
min2 = min1;
min1 = val;
}
else if (val < min2) {
min2 = val;
}
}
int p1 = max1*max2*max3,p2=max1*min1*min2;
return (p1 > p2 ? p1 : p2);
}
//合并两个排好序的数组,注意判断i的位置
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1, last = m + n - 1;
while (j >= 0) {
nums1[last] = (i >= 0 && nums1[i]>nums2[j]) ? nums1[i--] : nums2[j--];
}
//one line
//while(n>0) A[m+n-1] = (m==0||B[n-1] > A[m-1]) ? B[--n] : A[--m];
}
//将数组中为0的移动到前面,找到第一个零后面每次交换0和非零的位置
void moveZeroes(vector<int>& nums) {
int j = 0, size = nums.size();
if (!size || size == 1)return;
while (0 != nums[j])j++;
for (int i = j + 1; i<size; ++i) {
if (0 != nums[i]) {
swap(nums[i], nums[j++]);
}
}
}
//寻找插入位置,找不到就找应该能插入的位置
int searchInsert(vector<int>& nums, int target) {
int right = nums.size() - 1, left = 0, mid = right / 2;
while (left <= right)//注意=号
{
if (nums[mid] == target) {
return mid;
}
else if (nums[mid]<target) {
left = mid + 1;
}
else {
right = mid - 1;
}
mid = ((left + right) / 2);
}
return left;
}
//是否有重复
bool containsDuplicate(vector<int>& nums) {
set<int> s(nums.begin(), nums.end());
// for(auto val:nums){
// s.insert(val);
// }
return s.size() == nums.size() ? false : true;
}
//是否有间隔小于k的重复数字
bool containsNearbyDuplicate(vector<int>& nums, int k) {
set<int>s;
if (k <= 0)return false;
if (k>nums.size())k = nums.size() - 1;
int size = nums.size();
for (int j = 0; j<size; ++j) {
if (j>k)s.erase(nums[j - k - 1]);
if (s.find(nums[j]) != s.end())return true;
s.insert(nums[j]);
}
return false;
}
//杨辉三角线
vector<vector<int> > generate(int numRows) {
vector<vector<int> > r(numRows);
for (int i = 0; i < numRows; i++) {
r[i].resize(i + 1);
r[i][0] = r[i][i] = 1;
for (int j = 1; j < i; j++)
r[i][j] = r[i - 1][j - 1] + r[i - 1][j];
}
return r;
}
//杨辉三角线某一行
vector<int> getRow(int rowIndex) {
vector<int> vi(rowIndex + 1);
vi[0] = 1;
for (int i = 0; i <= rowIndex; ++i)
{
for (int j = i; j > 0; --j)
{
vi[j] = vi[j] + vi[j - 1];
}
}
return vi;
}
//返回后面减去前面的某个数最大的差值
int maxProfit(vector<int>& prices) {
if (!prices.size())return 0;
// priority_queue<int, vector<int>, greater<int> >que;
// que.push(prices[0]);
// int dif=0,minPrice=0,tmp=0;
// for(int i=1;i<prices.size();++i){
// minPrice=que.top();//cout<<minPrice;
// tmp=prices[i]-minPrice;
// if(dif<tmp)dif=tmp;
// que.push(prices[i]);
// }
int minPrice = INT_MAX, dif = 0;
for (auto val : prices) {
minPrice = min(minPrice, val);
dif = max(dif, val - minPrice);
}
return dif;
}
// 最长递增子序列
int findLengthOfLCIS(vector<int>& nums) {
if (!nums.size())return 0;
if (1 == nums.size())return 1;
int len = 1, temp = 1;
for (int i = 1; i<nums.size(); ++i) {
if (nums[i] - nums[i - 1]>0) {
temp++;
len = len>temp ? len : temp;
}
else {
temp = 1;
}
}
return len;
}
// 倒数第三大的数字,不存在则返回最大值
int thirdMax(vector<int>& nums) {
set<int> top3;
for (int num : nums) {
top3.insert(num);
if (top3.size() > 3)
top3.erase(top3.begin());
}
return top3.size() == 3 ? *top3.begin() : *top3.rbegin();
}
//找出0~n中缺失的那个数,相加于再增加这些数变化为找成对数中缺少的那个数
int missingNumber(vector<int>& nums) {
int result = nums.size();
int i = 0;
for (int num : nums) {
result ^= num;
result ^= i;
i++;
}
return result;
}
//至少间隔一个空才能种花,最多种多少
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
flowerbed.insert(flowerbed.begin(), 0);
flowerbed.push_back(0);
for (int i = 1; i < flowerbed.size() - 1; ++i)
{
if (flowerbed[i - 1] + flowerbed[i] + flowerbed[i + 1] == 0)
{
--n;
++i;
}
}
return n <= 0;
}
//加1,绝妙之处在于没进位就可以停止了i >= 0 && carry
vector<int> plusOne(vector<int> &digits) {
bool carry = true;
for (int i = digits.size() - 1; i >= 0 && carry; i--) {
carry = (++digits[i] %= 10) == 0;
}
if (carry) {
digits.insert(digits.begin(), 1);
}
return digits;
}
//能够使数组有序的最短排序连续子序列,1236548只需要将654排好整个数组就有序了
int findUnsortedSubarray(vector<int>nums) {
int size = nums.size(), begin = -1, end = -1, maxNum = INT_MIN, minNum = INT_MAX;
for (int i = 0; i < size; i++)
{
maxNum = max(nums[i], maxNum);
minNum = min(nums[size - i - 1], minNum);
if (nums[i] < maxNum)end = i;
if (nums[size - i - 1] > minNum)begin = size - i - 1;
}cout << end << begin;
if (end == -1)return 0;//也可以设置begin=-2,这样的话直接下一句的return就行不用这句话判断
return end - begin + 1;
}
//将数组分为两两一组,使得Σmin(ai,bi)最小,排序取1,3,5...
int arrayPairSum(vector<int>& nums) {
int nSum = 0;
sort(nums.begin(), nums.end());
for (int i = 0; i<nums.size(); ++i) {
if (0 == i % 2)nSum += nums[i];
}
return nSum;
}
//重新划分vector的行列
vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
int rows = nums.size(), cols = nums[0].size(), j = 0,size=rows*cols;
if (r*c!=size)return nums;
vector<vector<int>> reshap(r);
for (int i = 0; i<r; ++i) {
vector<int> tmp(c);
for (int k = 0; k<c; ++k) {
j = i*c + k;
tmp[k] = nums[j / cols][j % cols]; //cout << tmp[j];
}
reshap[i] = tmp;
}
return reshap;
}
//图像平滑
bool isValid(int& rows, int& cols, int i, int j) {//cout<<i<<j<<endl;
if (i<0 || i >= rows)return false;
if (j<0 || j >= cols)return false;
return true;
}
vector<vector<int>> imageSmoother(vector<vector<int>>& M) {
int rows = M.size(), cols = M[0].size(), val = 0;
vector<vector<int>> res(rows);
for (int i = 0; i<rows; ++i) {
vector<int> tmp(cols);
for (int j = 0; j<cols; ++j) {
int counts = 0;
val = 0;
if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
for (int r = -1; r <= 1; ++r) {
for (int c = -1; c <= 1; ++c) {
if (isValid(rows, cols, i + r, j + c)) {
val += M[i + r][j + c];
++counts;
}
}
}
tmp[j] = counts ? val / counts : 0; cout << counts;
}
else {
tmp[j] = (M[i - 1][j - 1] + M[i - 1][j] + M[i - 1][j + 1] + M[i][j - 1] + M[i][j] + M[i][j + 1] + M[i + 1][j - 1] + M[i + 1][j] + M[i + 1][j + 1]) / 9;
}
}
res[i] = tmp;
}
return res;
}
//一段时间内股票最多能赚多少,涨了就卖连续涨的情况其实今天买明天卖和买最低最高再卖一个意思
int maxPeriodProfit(vector<int>& prices) {
int size = prices.size(),res = 0;
for (int i = 1; i<size; ++i) {
if (prices[i] - prices[i - 1]>0)res += prices[i] - prices[i - 1];
}
return res;
}
//最长连续子串和
int maxSubArray(vector<int>& nums) {
int sum = 0, max = INT_MIN, size = nums.size();
for (auto val:nums) {
max = max>(sum+= val) ? max : sum;
sum = sum>0 ? sum : 0;
}
return max;
}
//n个数字中有几个数字被他们中的其他数字取代了,找出这些消失的数字数组中有重复的数,他们的值都小于数组长度n,找出缺失的数 https://discuss.leetcode.com/topic/65944/c-solution-o-1-space
/*将数字所指向的位置的数改为负数,再扫描一遍数组,如果不是负数,那么i+1不在这个数组里面,
极端例子,11111,只有a[1-1]被设置为负数,其他的都是整数,缺少2345
取出每个数的绝对值-1,将这个下标中的数置为负数,再扫描一遍没有被置为负数说明数组中没有i+1这个数字
*/
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> res;
int index = 0;
for (auto val : nums) {
index = abs(val) - 1;
nums[index] = nums[index]<0 ? nums[index] : -nums[index];
}
for (int i = 0; i<nums.size(); ++i) {
if (nums[i]>0)res.push_back(i + 1);
}
return res;
}
//是否能够只修改一个数字达到数组非降序
/*
24156...对于1而言他只能被修改为4
14156...对于1而言将4修改为1更好
4156...i小于2将4改为1更好
*/
bool checkPossibility(vector<int>& nums) {
if (nums.size() <= 1)return true;
int times = 0, pre = nums[0];
for (int i = 1; i<nums.size(); ++i) {
if (pre>nums[i] && times++)return false;//运行到&&会times判断后自动加1
if (pre>nums[i] && i - 2 >= 0 && nums[i - 2]>nums[i])continue;//虽然没修改,但默认pre为前一个,相当于修改了
pre = nums[i];//相当于将前一个改小了
}
return true;
}
//1~n是否有k个数之和为n
void isFound(vector<vector<int> >&res, vector<int>&tmp, int k, int n, int&sum) {
if (k == 0) {
if (sum == n) { res.push_back(tmp); return; }
else { return; }
}
for (int i = tmp.empty() ? 0 : tmp.back(); i < 9; ++i) {
if (sum + i + 1 > n)break;
sum += i + 1;
tmp.push_back(i + 1);
isFound(res, tmp, k - 1, n, sum);
sum -= i + 1;
tmp.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
int sum = 0;
vector<vector<int> >res;
vector<int> tmp;
isFound(res, tmp, k, n, sum);
return res;
}
//一个数组中连续数组和大于指定数的最短长度
int minSubArrayLen(int s, vector<int>& nums) {
int sum = 0, len = 0, res = INT_MAX;
for (int i = 0, j = 0; i<nums.size() && j <= nums.size();) {
if (sum >= s) {
res = res<len ? res : len;
sum -= nums[i++];
len--;
continue;
}
sum += nums[j++];
len++;
}
return res = res == INT_MAX ? 0 : res;
}
//数组中最多的联通邻域(上下左右为1算联通)
/*
1100
1101
0100--->5
*/
int connectNum(int i, int j, vector<vector<int> >& grid) {
int total = 1, rows = grid.size(), cols = grid[0].size();
grid[i][j] = 2;
vector<int> pos{ -1,0,1,0,-1 };
for (int ii = 0; ii<4; ++ii) {
int r = i + pos[ii], c = j + pos[ii + 1];
if (r >= 0 && r<rows&&c >= 0 && c<cols&&grid[r][c] == 1) {
total += connectNum(r, c, grid);
}
}
return total;
}
int maxAreaOfIsland(vector<vector<int>>& grid) {
int rows = grid.size(), cols = grid[0].size(), tmp = 0, res = 0;
for (int i = 0; i<rows; ++i) {
for (int j = 0; j<cols; ++j) {
if (grid[i][j] == 1) {
res = max(res, connectNum(i, j, grid));
}
}
}
return res;
}
void setOne(vector<vector<int>>&grid) {
for (int i = 1; i < grid.size() - 1; ++i) {
for (int j = 1; j < grid[0].size()-1 ; ++j) {
if (grid[i][j] == 0) {
if (grid[i - 1][j] == 1 && grid[i + 1][j] == 1 && grid[i][j - 1] == 1 && grid[i][j + 1] == 1) {
grid[i][j] = 1;
}
}
}
}
}
//三角形顶部到最下面一层的最小代价路径
int pathVal(int rows, int row, int index, vector<vector<int>>& triangle) {
if (row == rows)return triangle[row][index];
int lVal = INT_MAX, rVal = INT_MAX;
lVal = pathVal(rows, row + 1, index, triangle);
rVal = index<row + 1 ? pathVal(rows, row + 1, index + 1, triangle) : rVal;
return min(lVal, rVal) + triangle[row][index];
}
int minimumTotalRec(vector<vector<int>>& triangle) {
int res = 0, rows = triangle.size(), row = 0, index = 0;
res = pathVal(rows - 1, row, index, triangle);
return res;
}
/*
动态规划 从最后一层开始,用一个vector记录最小的代价,没每个i位置而言,为min(v[i],v[i+1])+triangle[i];这个vector保存了前一层的最小代价,因此节省了很多空间
*/
int minimumTotal(vector<vector<int>>& triangle) {
int rows = triangle.size() - 1;
vector<int> minVal = triangle.back();
for (int i = rows - 1; i >= 0; --i)
{
for (int j = 0; j < i + 1; ++j)
{
minVal[j] = min(minVal[j], minVal[j + 1]) + triangle[i][j];
}
}
return minVal[0];
}
//中序后序构造二叉树
int findInVec(vector<int>& v, int left, int right, int n) {
int i = 0;
for (int i = left; i <= right; ++i) {
if (v[i] == n)return i;
}
return -1;
}
TreeNode* buildTree(int left, int right, vector<int>& inorder, vector<int>& postorder, int ps, int pe) {
if (left > right || ps > pe)return nullptr;
int val = postorder[pe];
TreeNode *root = new TreeNode(val);
int piv = findInVec(inorder, left, right, val);
root->left = buildTree(left, piv - 1, inorder, postorder, ps, ps + piv - left - 1);
root->right = buildTree(piv + 1, right, inorder, postorder, ps + (piv - left), pe - 1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (!postorder.size() || !inorder.size() || postorder.size() != inorder.size())return nullptr;
int size = postorder.size();
return buildTree(0, size - 1, inorder, postorder, 0, size - 1);
}
//中序后序构造树
TreeNode* buildTreeip(vector<int>& preorder, int ps, int pe, vector<int>& inorder, int is, int ie, map<int, int>& hm) {
if (ps>pe || is>ie)return nullptr;
TreeNode* root = new TreeNode(preorder[ps]);
int index = hm[preorder[ps]];
root->left = buildTreeip(preorder, ps + 1, ps + index - is, inorder, is, index - 1, hm);
root->right = buildTreeip(preorder, ps + index - is + 1, pe, inorder, index + 1, ie, hm);
return root;
}
TreeNode* buildTreeip(vector<int>& preorder, vector<int>& inorder) {
if (!preorder.size() || !inorder.size() || preorder.size() != inorder.size())return nullptr;
map<int, int> hm;
int size = preorder.size() - 1;
int i = 0;
for (auto val : inorder) {
hm[val] = i++;
}
return buildTreeip(preorder, 0, size, inorder, 0, size, hm);
}
//总共有多少个连续子数组和为k
/*
用一个哈希表存储每一个元素之前的累加和,1,8,2,3,8 --k=13时,在3的位置累加和为14,只要查看之前有没有为14-k=1的累加和即可,这段之间的数字和为k
同理,还可以采用哈希表存储%k的结果,如果下次累加和如果余数如果已经出现则说明这段数字之间有累加了nk的数据
*/
int subarraySum(vector<int>& nums, int k) {
map<int, int>resTmp;
resTmp[0] = 1;
int sum = 0, res = 0;
for (int i = 0; i<nums.size(); ++i) {
sum += nums[i];
res += resTmp[sum - k];
resTmp[sum]++;
}
return res;
}
//不含有重复元素的全部子集,位图法 https://leetcode.com/problems/subsets/discuss/
/*
每一个位置的数字有两种状态01,一共2^n个,0~2^n中的二进制代表这个位置有或无
*/
vector<vector<int>> subsets(vector<int>& nums) {
sort(nums.begin(), nums.end());
int num_subset = pow(2, nums.size());
vector<vector<int> > res(num_subset, vector<int>());
for (int i = 0; i < nums.size(); i++)
for (int j = 0; j < num_subset; j++)
if ((j >> i) & 1)//对这么多的集合右移i位(检验第i个数字所在位的01情况)
res[j].push_back(nums[i]);
return res;
}
//递归法
vector<vector<int>> subsetsRec(vector<int>& nums, int n, vector<int>&tmp, vector<vector<int>>& res) {
res.push_back(tmp);
for (int i = n; i<nums.size(); ++i) {
tmp.push_back(nums[i]);
subsetsRec(nums, i + 1, tmp, res);
tmp.pop_back();
}
return res;
}
vector<vector<int>> subsetsRec(vector<int>& nums) {
int n = 0;
sort(nums.begin(), nums.end());
vector<int> tmp{};
vector<vector<int> > res;
subsetsRec(nums, n, tmp, res);
return res;
}
//正向构造,初始[]->[] [1]->[] [1] [2] [1 2]...对于每一个数字,先push_back已有的,并将这个数字放进集合里
vector<vector<int>> subsetsForward(vector<int>& nums) {
sort(nums.begin(), nums.end());
int size = nums.size();
vector<vector<int>> res(1, vector<int>());
for (int i = 0; i<size; ++i) {
int n = res.size();
for (int j = 0; j<n; ++j) {
res.push_back(res[j]);
res.back().push_back(nums[i]);
}
}
return res;
}
//含有重复数字元素的全部子集 https://discuss.leetcode.com/topic/3601/simple-iterative-solution
/*每次都对要插入的数字判断,如果和前一个重复的话,它只要插入到最近一次新增的那些vector就可以了
*/
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
int n = 0, start = 0, size = 0;
sort(nums.begin(), nums.end());
vector<vector<int> > res(1, vector<int>());
for (int i = 0; i < nums.size(); ++i) {
start = i >= 1 && nums[i] - nums[i - 1] == 0 ? size : 0;
size = res.size();
for (int j = start; j < size; ++j) {
res.push_back(res[j]);
res.back().push_back(nums[i]);
}
}
return res;
}
//将数组中的0,1,2分类
void sortColors(vector<int>& nums) {
//sort(nums.begin(),nums.end());
int left = 0, right = nums.size() - 1, k = 0;
for (int i = 0; i<nums.size(); ++i) {
while (nums[i] == 2 && i<right)swap(nums[i], nums[right--]);
while (nums[i] == 0 && i>left)swap(nums[i], nums[left++]);
}
}
//二维字符矩阵,模板匹配 https://discuss.leetcode.com/topic/9826/my-19ms-accepted-c-code
/*
对每个位置和首字母进行匹配,如果不越界字符相同没有访问过,则对其他四个方向进行下一个匹配,如果已经是最后一个了,且完全匹配了则返回true;
对四个方向只要有一个已经返回true了就直接return true,其中为了避免在迭代过程中发生回溯的情况先将当前置为'\0',后续变为换回去
*/
bool exist(vector<vector<char>>& board, const char* word, int i, int j) {
if (i<0 || i >= board.size() || j<0 || j >= board[0].size() || board[i][j] == '\0' || *word != board[i][j])return false;
if (*(word + 1) == '\0')return true;
char c = board[i][j];
board[i][j] = '\0';
if (exist(board, word + 1, i, j - 1) || exist(board, word + 1, i, j + 1) || exist(board, word + 1, i - 1, j) || exist(board, word + 1, i + 1, j))return true;
board[i][j] = c;
return false;
}
bool exist(vector<vector<char>>& board, string word) {
auto p = word.c_str();
int len = word.length();
int m = board.size(), n = board[0].size();
for (int i = 0; i<m; ++i) {
for (int j = 0; j<n; ++j) {
bool res = exist(board, p, i, j);
if (res)return true;
}
}
return false;
}
//二维数组从左上角到右下角的最短路径长度
/*动态规划 f[i j]=min(f[i-1 j],f[i j-1])+val[i][j]注意初始化第一行f[i j]以及ij合法性判断
*/
int minPathSum(vector<vector<int>>& grid) {
if (grid.size() == 0)return 0;
vector<vector<int>> pathVal(grid.size(), vector<int>(grid[0].size(), 0));
pathVal[0][0] = grid[0][0];
for (int i = 1; i<grid[0].size(); ++i)pathVal[0][i] += pathVal[0][i - 1] + grid[0][i];
for (int i = 1; i<grid.size(); ++i) {
for (int j = 0; j<grid[0].size(); ++j) {
if (j - 1<0) pathVal[i][j] = pathVal[i - 1][j] + grid[i][j];
if (i - 1<0) pathVal[i][j] = pathVal[i][j - 1] + grid[i][j];
if (i - 1 >= 0 && j - 1 >= 0)pathVal[i][j] = min(pathVal[i - 1][j], pathVal[i][j - 1]) + grid[i][j];
}
}
return pathVal[grid.size() - 1][grid[0].size() - 1];
}
//坐标轴上有i个线段,哪两个线段|1|111|l||之间能装最多的水 https://leetcode.com/problems/container-with-most-water/discuss/
/*开始最有可能就是最远端两个之间能装最多水,装水取决于最矮的那个棍子,要比最外端的两个棍子围起来的水多,必然将矮的那一头往里面移动寻找更高的棍子
*/
int maxArea(vector<int>& height) {
int maxVal = 0, l = 0, r = height.size() - 1, h = 0;
while (l<r) {
h = min(height[l], height[r]);
maxVal = max(h*(r - l), maxVal); cout << maxVal;
while (height[r] <= h)--r;
while (height[l] <= h)++l;
}
return maxVal;
}
//地面上有n个高度不一的水槽,最多能盛多少水 https://discuss.leetcode.com/topic/18731/7-lines-c-c
//二维数组任意一个数为0,其行列都置为0
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size(), flag = 1;
for (int i = 0; i<m; ++i) {
if (matrix[i][0] == 0)flag == 0;
for (int j = 1; j<n; ++j) {
if (matrix[i][j] == 0) {
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (int i = m - 1; i >= 0; ++i) {
for (int j = n - 1; j>0; ++j) {
if (matrix[i][0] == 0 || matrix[0][j] == 0)matrix[i][j] = 0;
}
if (flag == 0)matrix[i][0] = 0;
}
}
//找出循环队列最小值456780123 https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/discuss/
/*如果nums[i]<nums[j]说明有序,否则就看mid与右边的大小关系,注意右边=mid而不是mid+1
*/
int findMin(vector<int>& nums) {
// int minNum=nums[0], size=nums.size();
// for(int i=1;i<size;++i){
// if(nums[i]<minNum)return nums[i];
// }
// return minNum;
int i = 0, j = nums.size() - 1, mid = 0;
while (i<j) {
if (nums[i]<nums[j])return nums[i];
mid = (j + i) / 2;
if (nums[mid]>nums[j]) {
i = mid + 1;
}
else {
j = mid;
}
}
return nums[i];
}
//找出旋转队列的指定数字的位置, https://leetcode.com/problems/search-in-rotated-sorted-array/discuss/
/*先找出最小值的位置,注意right=mid而不是mid-1,然后寻找数组真正的mid,即为现在的mid+最小位置的值,相当于将原来的左移右移还原
*/
int search1(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1, mid = 0, newMid = 0;
while (left<right) {
mid = (left + right) / 2;
if (nums[mid]>nums[right])left = mid + 1;
else right = mid;
}//cout<<left;
int minNum = left;
left = 0, right = nums.size() - 1;
while (left <= right) {
mid = (left + right) / 2;
newMid = (mid + minNum) % nums.size();//cout<<mid;
if (nums[newMid] == target)return newMid;
if (nums[newMid]>target) {
right = mid - 1;
}
else {
left = mid + 1;
}//cout<<left<<right;
}
return -1;
}
//找出数组中重复的数,数字的值大于1<ni<n https://discuss.leetcode.com/topic/65944/c-solution-o-1-space
/*没有按号入座就是重复的,多余的*/
vector<int> findDuplicates(vector<int>& nums) {
vector<int> res;
int i = 0;
while (i < nums.size()) {
if (nums[i] != nums[nums[i] - 1]) swap(nums[i], nums[nums[i] - 1]);
else i++;
}
for (i = 0; i < nums.size(); i++) {
if (nums[i] != i + 1) res.push_back(nums[i]);
}
return res;
}
//下一个字典序
/*从右边向左边先寻找第一个小于右边值的位置index,如果不存在则直接反转即可,再从右边寻找第一个大于index处值的位置right,交换后将index到末尾的数全部反转
*/
void nextPermutation(vector<int>& nums) {
int index = -1;
for (int i = nums.size() - 2; i >= 0; --i) {
if (nums[i]<nums[i + 1]) {
index = i;
break;
}
}cout << index;
if (index == -1) {
reverse(nums.begin(), nums.end());
return;
}
int right = -1;
for (int i = nums.size() - 1; i>index; --i) {
if (nums[i]>nums[index]) {
right = i;
break;
}
}
cout << right;
swap(nums[right], nums[index]);
reverse(nums.begin() + index + 1, nums.end());
}
//输出第k个字典序
string getPermutation(string& s) {
int index = -1;
for (int i = s.size() - 2; i >= 0; --i) {
if (s[i]<s[i + 1]) {
index = i;
break;
}
}
if (index == -1) {
reverse(s.begin(), s.end());
return s;
}
int right = -1;
for (int i = s.size() - 1; i>index; --i) {
if (s[i]>s[index]) {
right = i;
break;
}
}
swap(s[index], s[right]);
reverse(s.begin() + index + 1, s.end());//cout<<s<<endl;
return s;
}
string getPermutation(int n, int k) {
string s, res;
if (n<2 || k<1)return to_string(n);
for (int i = 1; i<n + 1; ++i) {
s.append(to_string(i));
}
res = s;
for (int i = 0; i<k - 1; ++i) {
res = getPermutation(s);
}
return res;
}
//合并重合区间 [1,3],[2,6],[8,10],[15,18],--->[1,6],[8,10],[15,18]. https://discuss.leetcode.com/topic/20263/c-10-line-solution-easing-understanding/4
/*按区间起始大小排序,如果前一个的末尾小于后一个的开始则压入后一个,否则比较和后一个的末尾大小,用这个栈的back比较是亮点
*/
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e) : start(s), end(e) {}
};
vector<Interval> merge(vector<Interval>& insintervals) {
if (insintervals.empty()) return vector<Interval>{};
vector<Interval> res;
sort(insintervals.begin(), insintervals.end(), [](Interval& a, Interval& b) {return a.start < b.start; });
res.push_back(insintervals[0]);
for (int i = 1; i < insintervals.size(); i++) {
if (res.back().end < insintervals[i].start) res.push_back(insintervals[i]);
else
res.back().end = max(res.back().end, insintervals[i].end);
}
return res;
}