LeetCode中一些Array方面的题

主要是记录在刷题过程的一些题目


#include "stdafx.h"
#include
#include
#include
#include
#include 
#include 
#include 
#include
using namespace std;
struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
	
};

//返回排好序的数组中和为指定数的下标
vector twoSum(vector& numbers, int target) {
	int size = numbers.size();
	vector 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 twoSumNoOrder(vector& nums, int target) {
	//   int size=nums.size();
	//  vector res;
	//  int i=0,j=size-1;
	//  for(auto i=0;ihash;
	vector 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& 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& nums, int k) {
	if (k == 0)return;
	int tmp = 0, size = nums.size();
	vector::iterator it = nums.begin();
	for (int i = 0; i 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& nums, int k) {
	double res = INT_MIN, nSum = 0;
	int size = nums.size();
	for (int i = 0; i& nums) {
	int i = !nums.empty();
	for (auto val : nums) {
		if (val>nums[i - 1]) {
			nums[i++] = val;
		}
	}
	return i;
}
//数组去除指定数字
int removeElement(vector& nums, int val) {
	int i = 0;
	for (auto num : nums)if (val != num)nums[i++] = num;
	return i;
}
//三个数相乘最大,排序后最大的三个数相乘或者最小的两个数和最大的数相乘(考虑有负数的情况)
//或者遍历一遍寻找最大的三个数和最小的两个数
int maximumProduct(vector& 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& 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& nums1, int m, vector& 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& nums) {
	int j = 0, size = nums.size();
	if (!size || size == 1)return;
	while (0 != nums[j])j++;
	for (int i = j + 1; i& 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]& nums) {
	set s(nums.begin(), nums.end());
	// for(auto val:nums){
	//     s.insert(val);
	// }
	return s.size() == nums.size() ? false : true;
}
//是否有间隔小于k的重复数字
bool containsNearbyDuplicate(vector& nums, int k) {
	sets;
	if (k <= 0)return false;
	if (k>nums.size())k = nums.size() - 1;
	int size = nums.size();
	for (int j = 0; jk)s.erase(nums[j - k - 1]);
		if (s.find(nums[j]) != s.end())return true;
		s.insert(nums[j]);
	}
	return false;
}
//杨辉三角线
vector > generate(int numRows) {
	vector > 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 getRow(int rowIndex) {
	vector 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& prices) {
	if (!prices.size())return 0;
	// priority_queue, greater >que;
	// que.push(prices[0]);
	// int dif=0,minPrice=0,tmp=0;
	// for(int i=1;i& nums) {
	if (!nums.size())return 0;
	if (1 == nums.size())return 1;
	int len = 1, temp = 1;
	for (int i = 1; i0) {
			temp++;
			len = len>temp ? len : temp;
		}
		else {
			temp = 1;
		}
	}
	return len;
}
// 倒数第三大的数字,不存在则返回最大值
int thirdMax(vector& nums) {
	set 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& nums) {
	int result = nums.size();
	int i = 0;
	for (int num : nums) {
		result ^= num;
		result ^= i;
		i++;
	}
	return result;
}
//至少间隔一个空才能种花,最多种多少
bool canPlaceFlowers(vector& 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 plusOne(vector &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(vectornums) {
	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& nums) {
	int nSum = 0;
	sort(nums.begin(), nums.end());
	for (int i = 0; i> matrixReshape(vector>& 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> reshap(r);
	for (int i = 0; i tmp(c);
		for (int  k = 0; k= rows)return false;
	if (j<0 || j >= cols)return false;
	return true;
}
vector> imageSmoother(vector>& M) {
	int rows = M.size(), cols = M[0].size(), val = 0;
	vector> res(rows);
	for (int i = 0; i tmp(cols);
		for (int j = 0; j& prices) {
	int size = prices.size(),res = 0;
	for (int i = 1; i0)res += prices[i] - prices[i - 1];
	}
	return res;
}
//最长连续子串和
int maxSubArray(vector& 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 findDisappearedNumbers(vector& nums) {
	vector 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; i0)res.push_back(i + 1);
	}
	return res;
}
//是否能够只修改一个数字达到数组非降序
/*
24156...对于1而言他只能被修改为4
14156...对于1而言将4修改为1更好
4156...i小于2将4改为1更好
*/
bool checkPossibility(vector& nums) {
	if (nums.size() <= 1)return true;
	int  times = 0, pre = nums[0];
	for (int i = 1; inums[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 >&res, vector&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> combinationSum3(int k, int n) {
	int sum = 0;
	vector >res;
	vector tmp;
	isFound(res, tmp, k, n, sum);
	return res;
}
//一个数组中连续数组和大于指定数的最短长度
int minSubArrayLen(int s, vector& nums) {
	int sum = 0, len = 0, res = INT_MAX;
	for (int i = 0, j = 0; i= s) {
			res = res5
*/
int connectNum(int i, int j, vector >& grid) {
	int total = 1, rows = grid.size(), cols = grid[0].size();
	grid[i][j] = 2;
	vector 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= 0 && c>& grid) {
	int rows = grid.size(), cols = grid[0].size(), tmp = 0, res = 0;
	for (int i = 0; i>&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>& triangle) {
	if (row == rows)return triangle[row][index];
	int lVal = INT_MAX, rVal = INT_MAX;
	lVal = pathVal(rows, row + 1, index, triangle);
	rVal = index>& 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>& triangle) {
	int rows = triangle.size() - 1;
	vector 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& 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& inorder, vector& 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& inorder, vector& 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& preorder, int ps, int pe, vector& inorder, int is, int ie, map& 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& preorder, vector& inorder) {
	if (!preorder.size() || !inorder.size() || preorder.size() != inorder.size())return nullptr;
	map 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& nums, int k) {
	mapresTmp;
	resTmp[0] = 1;
	int sum = 0, res = 0;
	for (int i = 0; i> subsets(vector& nums) {
	sort(nums.begin(), nums.end());
	int num_subset = pow(2, nums.size());
	vector > res(num_subset, vector());
	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> subsetsRec(vector& nums, int n, vector&tmp, vector>& res) {
	res.push_back(tmp);
	for (int i = n; i> subsetsRec(vector& nums) {
	int n = 0;
	sort(nums.begin(), nums.end());
	vector tmp{};
	vector > res;
	subsetsRec(nums, n, tmp, res);
	return res;
}
//正向构造,初始[]->[] [1]->[] [1] [2] [1 2]...对于每一个数字,先push_back已有的,并将这个数字放进集合里
vector> subsetsForward(vector& nums) {
	sort(nums.begin(), nums.end());
	int size = nums.size();
	vector> res(1, vector());
	for (int i = 0; i> subsetsWithDup(vector& nums) {
	int n = 0, start = 0, size = 0;
	sort(nums.begin(), nums.end());
	vector > res(1, vector());
	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& nums) {
	//sort(nums.begin(),nums.end());
	int left = 0, right = nums.size() - 1, k = 0;
	for (int i = 0; ileft)swap(nums[i], nums[left++]);

	}
}
//二维字符矩阵,模板匹配 https://discuss.leetcode.com/topic/9826/my-19ms-accepted-c-code
/*
对每个位置和首字母进行匹配,如果不越界字符相同没有访问过,则对其他四个方向进行下一个匹配,如果已经是最后一个了,且完全匹配了则返回true;
对四个方向只要有一个已经返回true了就直接return true,其中为了避免在迭代过程中发生回溯的情况先将当前置为'\0',后续变为换回去
*/
bool exist(vector>& 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>& 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>& grid) {
	if (grid.size() == 0)return 0;
	vector> pathVal(grid.size(), vector(grid[0].size(), 0));
	pathVal[0][0] = grid[0][0];
	for (int i = 1; i= 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& height) {
	int maxVal = 0, l = 0, r = height.size() - 1, h = 0;
	while (l>& matrix) {
	int m = matrix.size(), n = matrix[0].size(), flag = 1;
	for (int i = 0; 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) {
	// int minNum=nums[0], size=nums.size();
	// for(int i=1;inums[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& nums, int target) {
	int left = 0, right = nums.size() - 1, mid = 0, newMid = 0;
	while (leftnums[right])left = mid + 1;
		else right = mid;
	}//cout<target) {
			right = mid - 1;
		}
		else {
			left = mid + 1;
		}//cout< findDuplicates(vector& nums) {
	vector 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& nums) {
	int index = -1;
	for (int i = nums.size() - 2; i >= 0; --i) {
		if (nums[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]index; --i) {
		if (s[i]>s[index]) {
			right = i;
			break;
		}
	}
	swap(s[index], s[right]);
	reverse(s.begin() + index + 1, s.end());//cout<[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 merge(vector& insintervals) {
	if (insintervals.empty()) return vector{};
	vector 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;
}



你可能感兴趣的:(面试编程)