数组相关算法

刷题汇总

第一章 数组
第二章 链表



前言

数组是连续存储的空间,利用下标索引的方式获取相应数据。


一、双指针

704.二分查找

int left=0,right=nums.size()-1;
while(left<=right){
	int mid = left+(right-left)/2;
	if(nums[mid]==target) {
		return mid;
	}
	else if(nums[mid]<target){
		left=mid+1;
	}
	else{
		right=mid-1;
	}
}

88.合并两个有序数组 easy

void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    int index = m + n - 1;
    m--, n--;
    while (m >= 0 && n >= 0) {
        nums1[index--] = max(nums1[m], nums2[n]);
        nums1[m] >= nums2[n] ? m-- : n--;
    }
    while (n >= 0) {
        nums1[n--] = nums2[n];
    }
}

33.搜索旋转排序数组

二分查找

15.三数之和

判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有和为 0 且不重复的三元组。
难点是去重!

vector<vector<int>> threeSum(vector<int>& nums) {
	//双指针
	sort(nums.begin(), nums.end());
	vector<vector<int>>result;
	for (int i = 0; i < nums.size(); i++) {
		//去重
		if (nums[i] > 0) return result;
		//去重
		if (i > 0 && nums[i - 1] == nums[i]) {
			continue;
		}
		int left = i + 1, right = nums.size() - 1;
		while (left < right) {
			if (nums[i] + nums[left] + nums[right] == 0) {  //存储结果,缩小查找范围
				result.push_back({ nums[i] , nums[left] , nums[right] });
				//去重
				while (left < right && nums[right] == nums[right - 1]) right--;
				while (left < right && nums[left] == nums[left + 1]) left++;
				right--;
				left++;
			}
			else if (nums[i] + nums[left] + nums[right] > 0) {
				right--;
				// 右值重复,去重
				while (left < right && nums[right] == nums[right + 1]) right--;
			}
			else {
				left++;
				// 左值重复,去重
				while (left < right && nums[left] == nums[left - 1]) left++;
			}
		}
	}
	return result;
}

27.移除元素 [快慢指针]

移除元素==保留正确元素
利用快指针找到正确的元素,将正确的元素赋值给慢指针。从而在慢指针的移动范围内都是正确的。

int removeElement(vector<int>& nums, int val){
	int left=0,right=0;
	for(;right<nums.size();right++){
		if(nums[right]!=val){
			nums[left++] = nums[right];
		}
	}
	return left;
}

977.有序数组的平方 [左右收缩双指针]

vector<int> sortedSquares(vector<int>& nums) {
	int left = 0, right = nums.size() - 1;
	vector<int> result(nums.size(), 0);
	int index = right;
	while (left <= right) {
		if (abs(nums[left]) > abs(nums[right])) {
			result[index--] = pow(nums[left], 2);
			++left;
		}
		else {
			result[index--] = pow(nums[right], 2);
			--right;
		}
	}
	return result;
}

补充math中常见函数

1.绝对值函数 fabs ( double x ) 与 abs ( int x )
2.取整函数 floor(double x) 与 ceil(double x)
3.指数函数 x ^y pow( double x , double y )
4.sqrt ( double x )开方函数
5.log( double x) 取对数函数
6.round( double x ) 四舍五入取整函数

209.长度最小的子数组 [滑动窗口](控制流量)

int minSubArrayLen(int target, vector<int>& nums) {
	int lenght = INT_MAX, sum = 0;
	int left = 0, right = 0;
	for (; right < nums.size(); right++) {
		sum += nums[right];
		while (sum >= target) {
			lenght = min(lenght, right - left + 1);
			sum -= nums[left++];
		}
	}
	return lenght == INT_MAX ? 0 : lenght;
}

二、排序

56.合并区间

31.下一个排列 【字节跳动】

题目示例非常不全,需要考虑清楚所有情况再解答
思路:题意不可扩展空间,1、第一次查找,从后向前找到第一个 n u m s [ i − 1 ] < n u m s [ i ] nums[i-1]<nums[i] nums[i1]<nums[i] i i i;2、第二次查找,从后向前找到第一个比 i i i大的值进行交换;3、反转后段数组 r e v e r s e ( n u m s . b e g i n ( ) + i + 1 , n u m s . e n d ( ) ) ; reverse(nums.begin() + i + 1, nums.end()); reverse(nums.begin()+i+1,nums.end());

41.缺失的第一个正数 【字节跳动+微软】

原地哈希
原地哈希

int firstMissingPositive(vector<int>& nums) {
	int n = nums.size();
	//对负数进行扩值操作
	for (auto& num : nums) {
		if (num <= 0) num = n + 1;
	}
	//将小于等于n的元素对应位置变为负数
	for (int i = 0; i < n; i++) {
		int num = abs(nums[i]);
		if (num <= n) nums[num - 1] = -abs(nums[num - 1]);
	}
	//返回第一个大于零的
	for (int i = 0; i < n; ++i) {
		if (nums[i] > 0) {
			return i + 1;
		}
	}
	return n + 1;
}

4.寻找两个正序数组的中位数 【腾讯+字节跳动】 hard

思路寻找两正序数组的分界线!

三、矩阵

54.螺旋矩阵

解题思路:
1、计算完整的圈数round;
2、逐圈计算,分四步;
3、计算可能存在的核心块;

vector<int> spiralOrder(vector<vector<int>>& matrix) {
	int row = matrix.size(), col = matrix[0].size();
	vector<int>result;
	int round = min(row, col) / 2;//顺时针转动的圈数
	for (int index = 0; index < round; index++) {
		for (int j = index; j < col - (index + 1); j++) {
			result.push_back(matrix[index][j]);
		}
		for (int i = index; i < row - (index + 1); i++) {
			result.push_back(matrix[i][col - (index + 1)]);
		}
		for (int j = col - (index + 1); j > index; j--) {
			result.push_back(matrix[row - (index + 1)][j]);
		}
		for (int i = row - (index + 1); i > index; i--) {
			result.push_back(matrix[i][index]);
		}
	}
	if (min(row, col) % 2) {
		if (row >= col) {
			for (int i = round; i < row - round; i++) {
				result.push_back(matrix[i][col / 2]);
			}
		}
		else {
			for (int j = round; j < col - round; j++) {
				result.push_back(matrix[row / 2][j]);
			}
		}
	}
	return result;
}

59.螺旋矩阵II

思路同 54.旋转矩阵

vector<vector<int>> generateMatrix(int n) {
	vector<vector<int>> result(n, vector<int>(n, 0));
	int count = 1;
	for (int round = 0; round < n / 2; round++) {
		for (int j = round; j < n - (round + 1); j++) {
			result[round][j] = count;
			count++;
		}
		for (int i = round; i < n - (round + 1); i++) {
			result[i][n - (round + 1)] = count;
			count++;
		}
		for (int j = n - (round + 1); j > round; j--) {
			result[n - (round + 1)][j] = count;
			count++;
		}
		for (int i = n - (round + 1); i > round; i--) {
			result[i][round] = count;
			count++;
		}
	}
	if (n % 2) {
		result[n / 2][n / 2] = n * n;
	}
	return result;
}

总结

参考博客:
代码随想录
力扣HOT100
力扣剑指offer
CodeTop

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值