算法第二天|977.有序数组平方,209.长度最小的子数组,59螺旋矩阵||

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、有序数组平方(力扣977)

实现思想1:先对数组平方然后使用快速排序

实现思想2:使用双指针算法

二、长度最小的子数组(力扣209)

三、螺旋矩阵||(力扣59)



前言

1.学习有序数组平方的双指针算法

2.滑动窗口算法

3.螺旋矩阵操作


提示:以下是本篇文章正文内容,下面案例可供参考

一、有序数组平方(力扣977)

实现思想1:先对数组平方然后使用快速排序

1.力扣写法

class Solution {
public:
    void quick_sort(vector<int> &array, int l, int r){
	    if(l >= r) return;
	    int x = array[(l+r)/2], i = l-1, j = r+1;
	    while(i < j){
		    do i++; while(x > array[i]);
		    do j--; while(x < array[j]);
		    if (i < j) swap(array[i], array[j]);
	    } 
	    quick_sort(array, l, j);
	    quick_sort(array, j+1, r); 
    }

    vector<int> sortedSquares(vector<int>& nums) {
        int size = nums.size();
        for (int i = 0; i < size; i++){
            nums[i] = nums[i]*nums[i];
        }
        quick_sort(nums, 0, nums.size()-1);
        return nums;
    }
};

2.2.自行创建数组并实现有序数组平方

#include <iostream>
#include <cmath> 
#include <vector>

using namespace std;

//第一种方式,先对数组进行平方,然后对平方的结果进行排序 
void function(vector<int> &array){
	int size = array.size();
	for (int i = 0; i < size; i++){
		array[i] = pow(array[i], 2);
	}
}

void quick_sort(vector<int> &array, int l, int r){
	if(l >= r) return;
	int x = array[(l+r)/2], i = l-1, j = r+1;
	while(i < j){
		do i++; while(x > array[i]);
		do j--; while(x < array[j]);
		if (i < j) swap(array[i], array[j]);
	} 
	quick_sort(array, l, j);
	quick_sort(array, j+1, r); 
}

int main(void){
	vector<int> array = {3, 1, 2, 5, 4};
	function(array);
	quick_sort(array, 0, 4);
	for (auto p : array) cout << p << ' ';
} 

实现思想2:使用双指针算法

1.力扣写法

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result;
        int k = nums.size()-1;
        result.resize(nums.size(), 0);
        for (int i = 0, j = nums.size() - 1; i <= j; ){
            if(nums[i]*nums[i] > nums[j]*nums[j]){
                result[k--] = nums[i]*nums[i];
                i++;
            }
            else{
                result[k--] = nums[j]*nums[j];
                j--;
            }
        }
        return result;
    }
};

2.自行创建数组并实现有序数组平方

#include <iostream>
#include <vector>

 using namespace std;
 
void function(vector<int> &nums, vector<int> &result){
	int k = nums.size() - 1;
	//将result数组的大小设置成和nums数组一样大,并把数组值全部初始成0  
	result.resize(nums.size(), 0);
	for (int i = 0, j = nums.size() - 1; i <= j;){
		//因为数组是有序的,所以值一定是依次从两边取值
		//当nums[i]的平方大于nums[j]的平方的时候
		//将num[i]的平方存到result数组最后一位否则就将nums[j]平方存入 
		if (nums[i]*nums[i] >= nums[j]*nums[j]){
			result[k--] =  nums[i]*nums[i];
			i++; 
		}
		else{
			result[k--] =  nums[j]*nums[j];
			j--;
		}
	}
}
 
 int main(void){
 	//这个nums数组一定是有序的才能使用上面的方法 
 	vector<int> nums = {-4, -3, -1, 0, 1, 3, 5};
 	vector<int> result;
	function(nums, result);
	//展示result数组 
	for (auto p: result){
		cout << p << ' ';
	}
 	return 0;
 }

二、长度最小的子数组(力扣209)

实现思想:使用双指针i和j,i用来表示最小子数组的头,j用来表示最小子数组的尾,只要目前最小子数组中的元素和达不到要求,j就向后移动,直到其中的元素和达到要求的数值,此时将该子数组的长度记录下来,并将i后移寻找下一个达标的子数组,如果找到长度更小的子数组就将之前的长度覆盖。

1.力扣写法

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i = 0;
        int sum = 0;
        int sublength;
        int result = INT32_MAX;
        for(int j = 0; j < nums.size(); j++){
            sum += nums[j];
            while(sum >= target){
                sublength = j - i + 1;
                result = result< sublength ? result : sublength;
                sum -= nums[i++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

2.自行创建数组实现长度最小的子数组

#include <iostream>
#include <vector>

using namespace std;

int function (vector<int> &nums, int s){
	int i = 0; // 起点指针
	int sum = 0;// 记录当前数组的和有没有达到目标值(sum是实时更新的)
	int sublength;// 记录最小数组的长度(sublength是实时更新的) 
	int result = INT32_MAX;// result用来保留最长度小的一个sublength 
	for (int j = 0; j < nums.size(); j++){ //j是终点指针 
		sum += nums[j];
		while(sum >= s){
			sublength = j - i + 1;//计算当前达标的数组长度 
			//如果result < sublength就让result = result否则就让 result = sublength 
			result = result < sublength ? result : sublength;
			sum -= nums[i++];
		}
	} 
	//如果result值没有改变就说明数组中的所有值加起来都达不到s, 返回0 
	//如果result值改变了就返回result的值 
	return result == INT32_MAX ? 0 :result;  
}

int main(void){
	vector<int> nums = {2, 3, 1, 2, 4, 3};
	//检查数组中使值加起来大于等于7得最小长度的数组 
	//在这个数组中就是[4, 3] 
	int result = function(nums, 7);
	cout << result;
	return 0;
} 

三、螺旋矩阵||(力扣59)

实现思想:每一个边的处理都遵循左闭右开的原则,n - offset表示每一次循环的边界

1.力扣写法

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int loop = n / 2;
        int count = 1;
        int mid = n / 2;
        int offset = 1;
        int i, j;
        while(loop--){
            i = startx;
            j = starty;
            for (j = starty; j < n-offset; j++){
                res[startx][j] = count++;
            }
            for (i = startx; i < n-offset; i++){
                res[i][j] = count++;
            }
            for (j; j > starty; j--){
                res[i][j] = count++;
            }
            for(i; i > startx; i--){
                res[i][j] = count++;
            }
            startx++;
            starty++;
            offset++;
        }
        if (n%2){
            res[mid][mid] = count;
        }
        return res;
    }
};

2.自行实现二维数组的创建赋值和输出

#include <iostream>
#include <vector>

using namespace std;

void function(vector<vector<int>> &res, int n){
	int startx = 0, starty = 0;//x和y的开始位置 
	int offset = 1; //控制每一条边的遍历长度,每次循环右边界收缩一位 
	int count = 1; //用来表示打印的数字 
	int loop = n / 2; //用来表示需要循环的次数
	int mid = n/2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
	int i, j;
	while(loop--){
		i = startx;
		j = starty;
		//循环创建上边 
		for (j = starty; j < n - offset; j++){
			res[startx][j] = count++;
		}
		//创建右边 
		for (i = startx; i < n - offset; i++){
			res[i][j] = count++;
		}
		//创建下边 
		for (;j > starty; j--){
			res[i][j] = count++;
		}
		//创建左边 
		for (; i > startx; i--){
			res[i][j] = count++;
		}
		//在创建完一圈后更新起始位置
		//并且将offset增加 
		startx++;
		starty++;
		offset++;
	} 
	//如果边是奇数的 那么中间的点就需要单独填充 
	if(n%2){
		res[mid][mid] = count;	
	} 

}

int main(void){
	int n;
	cin >> n;
	//创建二位数组vector 
	vector<vector<int>> res(n, vector<int>(n, 0));	
	function(res, n);
	//将创建的二维数组进行输出 
	for (int i = 0; i < n; i++) {
    	for (int j = 0; j < n; j++) {
        	cout << res[i][j] << "   ";
    	}
    	cout << endl;
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值