算法:數組part02: 209. 長度最小的子數組 + 59.螺旋矩陣II + 代碼隨想錄補充58.區間和 + 44. 開發商購買土地

算法:數組part02: 209. 長度最小的子數組 + 59.螺旋矩陣II+ 代碼隨想錄補充58.區間和 + 44. 開發商購買土地

209. 長度最小的子數組

題目:https://leetcode.cn/problems/minimum-size-subarray-sum/description/
文章講解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
視頻講解:https://www.bilibili.com/video/BV1tZ4y1q7XE(思想較難,看視頻復習)

思想

  • 找出長度最小的子數組,用暴力解法,兩層for循環列出所有的可能情況(以i為頭以j為尾,這樣i從頭遍歷到尾,找到以數組所以元素為頭的子數組)可以解題;
  • 要想用一層for實現上面的效果,就需要用到滑動窗口(雙指針)的思想,for循環滑動窗口的右邊界,左邊界在這層for的邏輯中去修改;就可以達到O(n)的時間復雜度;

解題

暴力解法
//C++版
class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {int result = INT32_MAX; // 最終的結果int sum = 0; // 子序列的數值之和int subLength = 0; // 子序列的長度for (int i = 0; i < nums.size(); i++) { // 設置子序列起點為isum = 0;for (int j = i; j < nums.size(); j++) { // 設置子序列終止位置為jsum += nums[j];if (sum >= s) { // 一旦發現子序列和超過了s,更新resultsubLength = j - i + 1; // 取子序列的長度result = result < subLength ? result : subLength;break; // 因為我們是找符合條件最短的子序列,所以一旦符合條件就break}}}// 如果result沒有被賦值的話,就返回0,說明沒有符合條件的子序列return result == INT32_MAX ? 0 : result;}
};
正解
class Solution {public int minSubArrayLen(int target, int[] nums) {//利用滑動窗口(左右指針指示滑動窗口兩端,本身還是雙指針的思想)int left=0;int sum=0;//初始的result需要設為整數的最大值int result=Integer.MAX_VALUE;//記錄滿足條件的子串長度int sublength=0;for(int right=0;right<nums.length;right++){sum+=nums[right];while(sum>=target){sublength=right-left+1;result=Math.min(sublength,result);sum-=nums[left++];}}return result==Integer.MAX_VALUE?0:result;}
}////這個是參考答案,要更好理解,上面的是我寫的
class Solution {// 滑動窗口public int minSubArrayLen(int s, int[] nums) {int left = 0;int sum = 0;int result = Integer.MAX_VALUE;for (int right = 0; right < nums.length; right++) {sum += nums[right];while (sum >= s) {result = Math.min(result, right - left + 1);sum -= nums[left++];}}return result == Integer.MAX_VALUE ? 0 : result;}
}

總結

for循環循環的是滑動窗口的右邊界,左邊界在這個循環邏輯的內部利用while()去改變;感覺這個思想要記下來,第一次接觸基本想不出;

59.螺旋矩陣II

題目:https://leetcode.cn/problems/spiral-matrix-ii/description/
文章鏈接:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html

思想

文章中總結的思路很好,要堅持循環不變量的原則:搞清區間的邊界,以及每次循環的判斷條件要一樣;
邊界確定:每行或每列的末尾不屬于本行,而作為下一行的開始
螺旋矩陣的n:n為偶數loop=2/n,n為奇數就需要單獨處理最內部的一個位置;

解題

class Solution {public int[][] generateMatrix(int n) {int nums[][]=new int[n][n];//循環圈數int loop=0;int startX=0;int startY=0;int i,j;//用來表示每行最后幾個不包含int offset=1;//用來表示填充的數字int count=1;int mid=n/2;while(loop<n/2){//下面的四個for就是模擬轉了一圈//首先是左上到右上for(j=startY;j<n-offset;j++){nums[startX][j]=count++;}//右上到右下for(i=startX;i<n-offset;i++){nums[i][j]=count++;}//右下到左下for(;j>startY;j--){nums[i][j]=count++;}//左下到左上for(;i>startX;i--){nums[i][j]=count++;}startX++;startY++;loop++;offset++;}//奇數的情況單獨給中間元素賦值if(n%2!=0){nums[mid][mid]=count;}return nums;}
}////這個是參考答案,要更好理解,上面的是我寫的
class Solution {public int[][] generateMatrix(int n) {int[][] nums = new int[n][n];int startX = 0, startY = 0;  // 每一圈的起始點int offset = 1;int count = 1;  // 矩陣中需要填寫的數字int loop = 1; // 記錄當前的圈數int i, j; // j 代表列, i 代表行;while (loop <= n / 2) {// 頂部// 左閉右開,所以判斷循環結束時, j 不能等于 n - offsetfor (j = startY; j < n - offset; j++) {nums[startX][j] = count++;}// 右列// 左閉右開,所以判斷循環結束時, i 不能等于 n - offsetfor (i = startX; i < n - offset; i++) {nums[i][j] = count++;}// 底部// 左閉右開,所以判斷循環結束時, j != startYfor (; j > startY; j--) {nums[i][j] = count++;}// 左列// 左閉右開,所以判斷循環結束時, i != startXfor (; i > startX; i--) {nums[i][j] = count++;}startX++;startY++;offset++;loop++;}if (n % 2 == 1) { // n 為奇數時,單獨處理矩陣中心的值nums[startX][startY] = count;}return nums;}
}

總結

  • 螺旋矩陣II的關鍵點在于循環不變量:確定邊界,循環條件不變;
  • 時間復雜度為O(n2);

代碼隨想錄補充58.區間和

題目+講解:https://www.programmercarl.com/kamacoder/0058.%E5%8C%BA%E9%97%B4%E5%92%8C.html

思想

  • 暴力解法:直接遍歷相應區間,計算總和的值,時間復雜度為O(m*n);
  • 最優解:空間換時間,用一個新數組,新數組的每個元素存儲給出數組前i位元素的和,用到時直接取相應的p[b]-p[a-1]即可;如果a=0,則結果直接為p[b];

解題

import java.util.Scanner;public class Main{public static void main(String[] args){Scanner scanner=new Scanner(System.in);int n=scanner.nextInt();int[] vec=new int[n];int presum=0;//定義一個新數組,每個位置存前i位元素的和int[] p=new int[n];int sum=0;//為原始數組、新數組每個元素賦值for(int i=0;i<n;i++){vec[i]=scanner.nextInt();presum+=vec[i];p[i]=presum;}//scanner.hashNextInt()用來判斷輸入是否還有下一個元素:即是否還需要求區間和while(scanner.hashNextInt()){int a=scanner.nextInt();int b=scanner.nextInt();if(a==0){sum=p[b];}else{sum=p[b]-p[a-1];}System.out.println(sum);}scanner.close();}
}////這個是參考答案,要更好理解,上面的是我寫的
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] vec = new int[n];int[] p = new int[n];int presum = 0;for (int i = 0; i < n; i++) {vec[i] = scanner.nextInt();presum += vec[i];p[i] = presum;}while (scanner.hasNextInt()) {int a = scanner.nextInt();int b = scanner.nextInt();int sum;if (a == 0) {sum = p[b];} else {sum = p[b] - p[a - 1];}System.out.println(sum);}scanner.close();}
}

總結

  • 區間和思想其實很好理解:就是犧牲空間先存儲前i位的和,后面做減法就好;

44. 開發商購買土地

思想:

暴力解法即利用三層for循環,第一層分別遍歷橫向的n-1個分割線和縱向的m-1個分割線,剩下兩層for用來求總和;時間復雜度為O(n3)
優化解法:(1)用區間和的思想,先用新數組1存橫向前i行元素的總和,再用新數組2存縱向前i行元素的總和;(2)也可以用優化暴力解法來代替三層for;時間復雜度O(n2)

解題

//暴力
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int[][] grid = new int[n][m];// 輸入區塊權值for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {grid[i][j] = scanner.nextInt();}}int minDiff = Integer.MAX_VALUE;// 1. 枚舉所有橫向分割線(i 從 0 到 n-2)for (int i = 0; i < n - 1; i++) {int sumA = 0;int sumB = 0;// 計算上半部分(A 區域)的總和for (int x = 0; x <= i; x++) {for (int y = 0; y < m; y++) {sumA += grid[x][y];}}// 計算下半部分(B 區域)的總和for (int x = i + 1; x < n; x++) {for (int y = 0; y < m; y++) {sumB += grid[x][y];}}int diff = Math.abs(sumA - sumB);if (diff < minDiff) {minDiff = diff;}}// 2. 枚舉所有縱向分割線(j 從 0 到 m-2)for (int j = 0; j < m - 1; j++) {int sumA = 0;int sumB = 0;// 計算左半部分(A 區域)的總和for (int x = 0; x < n; x++) {for (int y = 0; y <= j; y++) {sumA += grid[x][y];}}// 計算右半部分(B 區域)的總和for (int x = 0; x < n; x++) {for (int y = j + 1; y < m; y++) {sumB += grid[x][y];}}int diff = Math.abs(sumA - sumB);if (diff < minDiff) {minDiff = diff;}}System.out.println(minDiff);}
}//區間和思想
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int sum = 0;int[][] vec = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {vec[i][j] = scanner.nextInt();sum += vec[i][j];}}// 統計橫向int[] horizontal = new int[n];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {horizontal[i] += vec[i][j];}}// 統計縱向int[] vertical = new int[m];for (int j = 0; j < m; j++) {for (int i = 0; i < n; i++) {vertical[j] += vec[i][j];}}int result = Integer.MAX_VALUE;int horizontalCut = 0;for (int i = 0; i < n; i++) {horizontalCut += horizontal[i];result = Math.min(result, Math.abs((sum - horizontalCut) - horizontalCut));// 更新result。其中,horizontalCut表示前i行的和,sum - horizontalCut表示剩下的和,作差、取絕對值,得到題目需要的“A和B各自的子區域內的土地總價值之差”。下同。}int verticalCut = 0;for (int j = 0; j < m; j++) {verticalCut += vertical[j];result = Math.min(result, Math.abs((sum - verticalCut) - verticalCut));}System.out.println(result);scanner.close();}
}//暴力解法優化import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int sum = 0;int[][] vec = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {vec[i][j] = scanner.nextInt();sum += vec[i][j];}}int result = Integer.MAX_VALUE;int count = 0; // 統計遍歷過的行// 行切分for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {count += vec[i][j];// 遍歷到行末尾時候開始統計if (j == m - 1) {result = Math.min(result, Math.abs(sum - 2 * count));}}}count = 0;// 列切分for (int j = 0; j < m; j++) {for (int i = 0; i < n; i++) {count += vec[i][j];// 遍歷到列末尾時候開始統計if (i == n - 1) {result = Math.min(result, Math.abs(sum - 2 * count));}}}System.out.println(result);scanner.close();}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90669.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90669.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90669.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring 核心知識點梳理 1

目錄 Spring Spring是什么&#xff1f; Spring中重要的模塊 Spring中最重要的就是IOC(控制反轉)和AOP(面向切面編程) 什么是IOC DI和IOC之間的區別 為什么要使用IOC呢&#xff1f; IOC的實現機制 什么是AOP Aop的核心概念 AOP的環繞方式 AOP發生的時期 AOP和OOP的…

Kafka運維實戰 07 - kafka 三節點集群部署(混合模式)(KRaft 版本3.7.0)

目錄環境準備主機準備補充說明JDK安裝 (三臺主機分別執行)下載jdkjdk安裝kafka 部署(三臺主機分別執行)kafka 下載kafka 版本號結構解析kafka 安裝下載和解壓安裝包(3臺主機都執行)配置 server.properties &#xff08;KRaft 模式&#xff09;192.168.37.10192.168.37.11192.16…

linux內核與GNU之間的聯系和區別

要理解操作系統&#xff08;如 GNU/Linux&#xff09;的組成&#xff0c;需要明確 內核&#xff08;Kernel&#xff09; 和 GNU 工具鏈 各自的功能&#xff0c;以及它們如何協作構成完整的操作系統。以下是詳細分析&#xff1a;1. 內核&#xff08;Kernel&#xff09;的功能 內…

文件包含學習總結

目錄 漏洞簡介 漏洞原理 漏洞分類 漏洞防御 漏洞簡介 程序開發人員一般會把重復使用的函數寫到單個文件中&#xff0c;需要使用某個函數時直接調用此文件&#xff0c;而無需再次編寫&#xff0c;這種文件調用的過程一般被稱為文件包含。程序開發人員一般希望代碼更靈活&…

TQZC706開發板教程:創建PCIE項目

本例程基于zc706開發板&#xff0c;使用xdma核創建PCIE項目&#xff0c;最終實現插入主機可識別出Xilinx設備。在vivado中創建一個空的706項目。創建完成后添加IP核-->搜索xdma-->雙擊打開配置。添加XDMA核如下所示basic配置peic id中設置設備號等信息&#xff0c;這里保…

科技賦能景區生.態,負氧離子氣象監測站筑牢清新防線

負氧離子氣象監測站&#xff0c;如同景區空氣質量的堅固防線&#xff0c;默默守護著每一寸土地的清新。?它以精準的監測能力為防線基石。借助 “吸入式電容收集法”&#xff0c;能敏銳捕捉空氣中負氧離子的蹤跡&#xff0c;精準測量其濃度&#xff0c;同時將溫度、濕度、PM2.5…

AMD官網下載失敗,不讓賬戶登錄下載

別使用163郵箱 使用QQ郵箱&#xff0c;然后用GPT生成一個外國&#xff0c;比如日本的地區信息填上去就可以下載了

Elasticsearch-8.17.0 centos7安裝

下載鏈接 https://www.elastic.co/downloads/past-releases/elasticsearch-8-17-0 https://www.elastic.co/downloads/past-releases/logstash-8-17-0 https://www.elastic.co/cn/downloads/past-releases/kibana-8-17-0https://artifacts.elastic.co/downloads/elasticsearch/…

windows下SAS9.4軟件下載與安裝教程

SAS 9.4是SAS公司推出的一款功能強大的統計分析軟件&#xff0c;廣泛應用于數據分析、商業智能、預測分析、數據挖掘及統計建模等多個領域。數據處理與管理能力&#xff1a;SAS 9.4支持多種數據格式的導入導出&#xff0c;包括JSON、XML等&#xff0c;便于處理來自Web和API的數…

MyBatis-Plus極速開發指南

MyBatis-Plus簡介MyBatis-Plus 是一個 MyBatis 的增強工具&#xff0c;在 MyBatis 的基礎上只做增強不做改變&#xff0c;簡化開發&#xff0c;提高效率。它提供了以下主要特性&#xff1a;無侵入&#xff1a;只做增強不做改變&#xff0c;引入它不會對現有工程產生影響強大的 …

Django接口自動化平臺實現(五)

8. 測試用例執行 預期效果如下&#xff1a;用例執行邏輯如下&#xff1a;前端提交用例 id 列表到后臺&#xff0c;后臺獲取每一條用例的信息&#xff1b;后臺獲取域名信息、用例 id 列表&#xff1b;對用例的請求數據進行變量的參數化、函數化等預處理操作&#xff1b;根據先后…

一個沒有手動加分號引發的bug

最近因為分號的疏忽&#xff0c;導致出現了一個bug&#xff0c;記錄下來&#xff0c;分享給大家。 1、一個示例 給你下面這一段代碼&#xff0c;你根據經驗判斷一下運營結果 let [a,b] [a,b] let [x,y] [1,2] if(x < y){[x,y] [y,x][a,b] [b,a] }按照一般的理解&#xf…

Elasticsearch安全審計日志設置與最佳實踐

一、Elasticsearch安全審計簡介 審計日志&#xff08;Audit Logging&#xff09;用于記錄Elasticsearch中的安全相關事件&#xff0c;包括認證失敗、連接拒絕、數據訪問事件以及通過API對安全配置&#xff08;如用戶、角色、API密鑰&#xff09;的變更記錄。 注意&#xff1a;審…

算法訓練營day29 貪心算法③ 134. 加油站、135. 分發糖果 、860.檸檬水找零、406.根據身高重建隊列

貪心算法的第三篇博客&#xff0c;繼續腦筋風暴&#xff01; 134. 加油站 寫在前面 這道題規定了有解的話&#xff0c;必定為唯一解 貪心思路 直接從全局進行貪心選擇&#xff0c;情況如下&#xff1a; 情況一&#xff1a;如果gas的總和小于cost總和&#xff0c;那么無論從…

【09】C#入門到精通——C# 結構體對齊 與 常用數據 對應關系

文章目錄1 C# 結構體對齊1.1 默認對齊方式1.2 節對齊方式設置1.3 偏移量設置2 C#與C/C之間類型的對應關系1 C# 結構體對齊 1.1 默認對齊方式 struct默認對齊方式&#xff0c;結構體長度必須是&#xff0c;最大成員長度的整數倍&#xff0c;所以下面結構體大小是 24 (實際占用…

pytest 測試報告生成方案有哪些?

在 pytest 中&#xff0c;除了 Allure 和 HTMLTestRunner&#xff0c;還有許多其他生成測試報告的方法和插件。以下是一些常用的方案及其特點&#xff1a;1. pytest-html&#xff08;官方推薦&#xff09;特點&#xff1a;輕量級、易集成&#xff0c;生成獨立的 HTML 報告。安裝…

Unity中EditorPrefs與PlayerPrefs對比分析

Unity中EditorPrefs與PlayerPrefs對比分析 EditorPrefs與PlayerPrefs是Unity引擎中用于數據持久化的兩個核心類&#xff0c;分別用于于編輯器擴展與游戲運行時場景。以下從設計目標、存儲位置、數據類型、生命周期、安全性、使用場景等方面展開對比&#xff0c;并結合代碼示例說…

藍光中的愧疚

藍光中的愧疚活動結束那晚&#xff0c;深圳的空氣吸飽了水汽&#xff0c;沉甸甸地壓在胸口。我站在西鄉社區活動中心冰涼的玻璃門外&#xff0c;目送著最后一個離開的王老師。她關掉門廳的燈&#xff0c;電子門鎖合攏時發出輕微卻尖銳的“嘀”聲&#xff0c;像一根細針扎在我緊…

Linux: network: wireshark: esp attempt to detec null-encrypted esp payloads

最近看到一個pcap文件&#xff0c;里面有esp協議包&#xff0c;而且是明文/沒有加密的消息&#xff0c;為什么wireshark沒有將esp上層的tcp/sip消息沒有解出來。 類似于Info列只有ESP的信息。后來選中了協議選項里的&#xff1a;attempt to detect/decode NULL encrypted ESP p…

10分鐘搭建腳手架:Spring Boot 3.2 + Vue3 前后端分離模板

10分鐘搭建腳手架&#xff1a;Spring Boot 3.2 Vue3 前后端分離模板一、項目結構設計二、后端搭建&#xff08;Spring Boot 3.2&#xff09;1. 快速初始化&#xff08;使用 Spring Initializr&#xff09;2. 核心配置application.yml跨域配置 CorsConfig.java3. 安全配置Secur…