首页 > 编程语言 >代码随想录算法day2-数组2

代码随想录算法day2-数组2

时间:2024-08-29 11:53:29浏览次数:14  
标签:示例 int 随想录 sum day2 rht 算法 result 数组

题目1 209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的

子数组

[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

思路

这道题可以使用暴力法嵌套循环去解决,但这种方式的时间复杂度为O(n2)。另一种解决方法是使用双指针的滑动窗口法,右指针rht负责寻找满足大于target的情况,左指针负责缩小满足target情况的范围。通过考虑滑动窗口的最坏情况来确认时间复杂度,

1.左指针和右指针在循环内每次都要移动一次,时间复杂度为:

\[O(\sum_{i=1}^{n}(1+1))=O(2n)=O(n) \]

2.左指针只有最后一次从数组开头移动到数组的结尾,时间复杂度为:

\[O(\sum_{i=1}^{n-1}(1)+(1+n))=O(2n)=O(n) \]

通过这样分析可以得出滑动窗口法比暴力迭代法要高效。

代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX;
        int lft = 0, rht = 0;
        int sum = 0;
        while(rht < nums.size())
        {
            sum += nums[rht++];
            while(sum >= target)
            {
                result = min(result, rht - lft);
                sum -= nums[lft++];
            }
        }
        return result == INT_MAX ? 0 : result;
    }
};

题目2 59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:

输入:n = 1
输出:[[1]]

思路

这道题就是模拟题,将1-n*n按顺时针放入到矩阵中。顺时针放入则需要设置放置的顺序为[右,下,左,上],每次放置前也需要注意越界问题,有效区域为[0, n-1];此外,还需要注意放置的位置是否已经放置其他元素。这道题的算法复杂度为:

\[O(\sum_{i=1}^{n}(\sum_{i=1}^{n-2}(1) + 2*2))=O(n^2) \]

代码

//设置的方向
enum orient{rht = 0,down,lft,up};
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n, INT_MAX));
        int cur = 1;
        int x = 0, y = -1;
        int nextStep = orient::rht;
        while(cur <= n*n)
        {
            if(nextStep == orient::rht)
            {
                if(y+1 < n && result[x][y+1] == INT_MAX)
                {
                    result[x][++y] = cur;
                }
                else
                {
                    nextStep = orient::down;
                    continue;
                }
            }
            else if(nextStep == orient::down)
            {
                if(x+1 < n && result[x+1][y] == INT_MAX)
                {
                    result[++x][y] = cur;
                }
                else
                {
                    nextStep = orient::lft;
                    continue;
                }  
            }
            else if(nextStep == orient::lft)
            {
                if(y-1 >= 0 && result[x][y-1] == INT_MAX)
                {
                    result[x][--y] = cur;
                }
                else
                {
                    nextStep = orient::up;
                    continue;
                }  
            }
            else if(nextStep == orient::up)
            {
                if(x-1 >= 0 && result[x-1][y] == INT_MAX)
                {
                    result[--x][y] = cur;
                }
                else
                {
                    nextStep = orient::rht;
                    continue;
                }  
            }            
            cur++;
        }
        return std::move(result);
    }
};

题目3 区间和

题目描述

给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。

输入描述

第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间下标:a,b (b > = a),直至文件结束。

输出描述

输出每个指定区间内元素的总和。

输入示例
5
1
2
3
4
5
0 1
1 3
输出示例
3
9
提示信息

数据范围:
0 < n <= 100000

思路

  1. 可以用暴力遍历法,但是提交后会发现超时,因为时间复杂度为O(n*m)
  2. 可以使用前缀和来处理这道题目,前缀和指的是将数组中的每个元素和之前的所有元素累加并记录到数组对应位置,当需要计算[a,b]元素之间的总和时,只需要\(\sum_{i=1}^{b}(elem(i)) - \sum_{i=1}^{a-1}(elem(i))\)一步操作就行了,而累加操作之前已经完成了,通过这种方法得出的时间复杂度为O(n+m)

代码

#include <iostream>
using namespace std;
int main()
{
    int num;
    cin >> num;
    int arr[num+1]{0};
    for(int i = 1; i <= num; i++)
    {
        cin >> arr[i];
        arr[i] += arr[i-1];
    }
    int lft, rht;
    while(cin >> lft >> rht)
    {
        cout << arr[rht + 1] - arr[lft] << endl;
    }
    return 0;
}

题目4 开发商购买土地

题目描述

在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。

现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。

然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。 为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。

注意:区块不可再分。

输入描述

第一行输入两个正整数,代表 n 和 m。

接下来的 n 行,每行输出 m 个正整数。

输出描述

请输出一个整数,代表两个子区域内土地总价值之间的最小差距。

输入示例
3 3
1 2 3
2 1 3
1 2 3
输出示例
0
提示信息

如果将区域按照如下方式划分:

1 2 | 3
2 1 | 3
1 2 | 3

两个子区域内土地总价值之间的最小差距可以达到 0。

数据范围:

1 <= n, m <= 100;
n 和 m 不同时为 1。

思路

思路1. 可以用暴力法来解决这道题,在将数据保存到数组后,横切(m-1)次,竖切(n-1)次并计算每块的总和并计算差值最后取最小值,但这样计算时间复杂度为:

\[O(n*m+(m-1)*n*m+(n-1)*n*m)=O(n^3)(假设n=m) \]

通过暴力法需要太多时间代价了。

思路2. 可以用前缀和的方法来解决这道题,因为每个区域都是要统计n个数或者m个数的和来进行计算的,因此可以将统计的过程分离出来保存到数组中。通过这种方法的时间复杂度为:

\[O(n*m+n*m+n+m)=O(n*m) \]

代码

#include <iostream>
#include <climits>
#include <algorithm>
using namespace std;
int main()
{
    int n, m;
    cin >> n >> m;
    int block[n][m];
    int hor[n+1]{0}, col[m+1]{0};
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            cin >> block[i][j];
            hor[i+1]+=block[i][j];
        }
        hor[i+1] += hor[i];
    }
    for(int j = 1; j <= m; j++)
    {
        for(int i = 1; i <= n; i++)
        {
            col[j] += block[i-1][j-1];
        }
        col[j] += col[j-1];
    }
    int result = INT_MAX;
    for(int i = 1; i < n; i++)
    {
        //cout << hor[i] << " ";
        result = min(result, abs(hor[n] - 2 * hor[i]));
    }
    //cout << endl;
    for(int j = 1; j < m; j++)
    {
        //cout << col[j] << " ";
        result = min(result, abs(col[m] - 2 * col[j]));
    }
    //cout << endl;
    cout << result << endl;
    return 0;
}

标签:示例,int,随想录,sum,day2,rht,算法,result,数组
From: https://www.cnblogs.com/code4log/p/18386375

相关文章

  • 算法-动态规划-完全背包
    0.动态规划五部曲:确定dp数组(dptable)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组1.完全背包问题完全背包问题中,每个物品都有无数个,可以重复选择。二维dp数组int[][]dp=newint[n][totalWeight+1];for(inti=0;i<n;++i){fo......
  • TimeWheel算法介绍及在应用上的探索
    作者:来自vivo互联网服务器团队-LiFan本文从追溯时间轮算法的出现,介绍了时间轮算法未出现前,基于队列的定时任务实现,以及基于队列的定时任务实现所存在的缺陷。接着我们介绍了时间轮算法的算法思想及其数据结构,详细阐述了三种时间轮模型的数据结构和优劣性。再次,我们介绍时......
  • EAS之WALT算法介绍
    EAS调度器缘起Linux内核的一直都使用完全公平调度器CFS(CompletelyFairScheduler)作为默认调度器,但是在使用中发现CFS如下几个问题。CFS主要是为了服务器性能优先场景而设计的,主要目标是最大限度地提高系统的吞吐量,CFS调度的目标是所有任务都平均分配到系统所有可用的CPU上......
  • 代码随想录day44 || 1143 最长公共子序列, 1035 不相交的线, 53 最大子序列和, 392 判
    1143最长公共子序列funclongestCommonSubsequence(text1string,text2string)int{ //思路和判断最长公共数组一样 //dp[i][j]表示以text1[i],text2[j]为结尾的最长公共子序列的长度 //iftext1[i]==text2[j]{dp[i+1][j+1]=dp[i][j]+1}else{dp[i+1][j+1]=......
  • 数据结构与算法(循环链表,双向链表)
    循环链表最后一个元素指向首元素带尾指针的循环链表合并双向链表双向链表:在单链表的每个结点里再增加一个指向其直接前驱的指针域prior,这样链表中就形成了有两个方向不同的链,故称为双向链表双向链表插入操作思路代码删除操作思路代码三种链表比较顺序表......
  • 用python写一个生产管理算法
    在生产管理中,算法可以帮助优化生产流程、提高效率和降低成本。一个简单的生产管理算法可能包括任务分配、资源调度、生产线平衡等方面。下面我将提供一个基本的任务分配算法的示例,这个算法将基于工人的技能和可用性来分配任务。```pythonclassWorker:def__init__(self,id......
  • 代码随想录算法训练营第四十三天 | 300.最长递增子序列 , 674. 最长连续递增序列 , 718.
    目录300.最长递增子序列 思路1.dp[i]的定义2.状态转移方程3.dp[i]的初始化4.确定遍历顺序 5.举例推导dp数组方法一:动态规划方法二:贪心心得收获 674.最长连续递增序列思路动态规划1.确定dp数组(dptable)以及下标的含义2.确定递推公式3.dp数组如何初始化4.......
  • 【408DS算法题】028基础-查找二叉树的最大值结点
    Index题目分析实现总结题目给定二叉树的根节点,找到二叉树中结点值最大的结点。分析实现对于查找二叉树中的最大值结点,在二叉树的遍历(DFS、层次遍历)的基础上进行修改可以轻松地达成这一目的。本文中选用的是相对直观的后序遍历,具体实现如下:BTNode*findMax(BTN......
  • 算法练习题03:分解质因数
    【问题描述】求出区间[a,b]中所有整数的质因数分解,统计一共有多少种不同的分法【输入格式】输人两个整数a和b。【输出格式】输出一行,一个整数,代表区间内质因数分解方法之和。【输入样例】610【输出样例】10【样例说明】6的质因数为2和3,一共有两个。7的质因数有......
  • 代码随想录算法训练营第二十九天(贪心 三)
    力扣题部分:134.加油站题目链接:.-力扣(LeetCode)题面:在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为......