日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

滑动窗口算法学习(一)

發(fā)布時(shí)間:2024/4/11 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 滑动窗口算法学习(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

思想

案例

連續(xù)元素最大之和

題目

分析

解法

求相同字母異序詞的下標(biāo)

題目

分析

解法

?


思想

滑動(dòng)窗口是指一個(gè)窗口,在一段區(qū)間上從左到右滑動(dòng),一直到區(qū)間的尾部,滑動(dòng)窗口的長度是可以動(dòng)態(tài)變化的(也可以固定)。一般情形下可以使用兩個(gè)指針分別指向窗口的兩邊,指針 i 指向窗口的左邊界,指針 j 指向窗口的右邊界

一些情況下,使用滑動(dòng)窗口處理字符串和數(shù)組 能提高效率,減少循環(huán)的嵌套使用,降低時(shí)間復(fù)雜度

滑動(dòng)窗口在網(wǎng)絡(luò)、大數(shù)據(jù)、流量控制等都有應(yīng)用。

下面將簡單介紹使用滑動(dòng)窗口處理字符串和數(shù)組的案例

案例

連續(xù)元素最大之和

題目

有一個(gè)整型數(shù)組,給定一個(gè)正整數(shù)k,求數(shù)組里連續(xù)k個(gè)數(shù)之和的最大值

Input : arr[] = {100, 200, 300, 400} ?k = 2

Output : 700

Input : arr[] = {1, 4, 2, 10, 23, 3, 1, 0, 20} ?k = 4

Output : 39

Input : arr[] = {2, 3} k = 3 Output : Invalid?

分析

上述問題能想到的最簡單的解法就是遍歷整個(gè)數(shù)組,從下標(biāo)為0開始,每次循環(huán)獲取k個(gè)連續(xù)的元素,計(jì)算其和之后比較獲得最大的和,這樣一來需要兩次循環(huán)(一層遍歷數(shù)組,一層遍歷k個(gè)元素)。

我們可以使用滑動(dòng)窗口來簡化代碼,因?yàn)閗是給定的固定值,所以窗口大小是固定的,相當(dāng)于窗口向右滑動(dòng)的時(shí)候,只需要減去左側(cè)的值(被移除窗口范圍的舊值),再加上右側(cè)的值(新移入窗口范圍的元素),就可以得到新的連續(xù)K個(gè)數(shù)之和,遍歷之后就能得到最大值,只需要一層遍歷就足夠了

解法

public void cal(int[] array, int k) {if (array.length == 0 || k <= 0 || k > array.length) {System.out.println("Invalid");return;}int maxSum = 0;//計(jì)算初始窗口位置的K個(gè)數(shù)之和for (int i = 0; i < k; i++) {maxSum += array[i];}int windows_sum = maxSum;for (int i = 1; i <= array.length - k; i++) {windows_sum = windows_sum - array[i - 1] + array[k + i - 1];if (windows_sum > maxSum) {maxSum = windows_sum;}}System.out.println("result= " + maxSum);}

求相同字母異序詞的下標(biāo)

題目

給定一個(gè)字符串s,和一個(gè)非空字符串p,要求尋找在s中所有和p滿足相同字母異序詞的子串(s,p全都是由26個(gè)小寫英文字母組成,并且長度不大于20100),并返回對(duì)應(yīng)的子串的第一個(gè)字符的下標(biāo)

Input: s: "cbaebabacd" p: "abc"

Output: [0, 6]

分析

要求找到相同字母異序詞,只需要子串里各個(gè)字母的個(gè)數(shù)相同即可。

1.使用map集合來表示子串,key為26個(gè)英文字母,value為每個(gè)字母對(duì)應(yīng)的個(gè)數(shù)

2.使用int數(shù)組來表示子串(每個(gè)元素表示對(duì)應(yīng)字母的個(gè)數(shù),第一個(gè)元素表示’a’的個(gè)數(shù),第二個(gè)表示’b’的個(gè)數(shù),以此類推…),每次滑動(dòng)的時(shí)候判斷目標(biāo)窗口和滑動(dòng)窗口里的int數(shù)組是否一致

解法

解法一:

使用map里記錄每個(gè)子串里的每個(gè)字母的元素個(gè)數(shù),由于采用判斷map是否有該元素的方式來加快遍歷速度,故每次判斷字母后需要減去1,每結(jié)束一次循環(huán)判斷還需要還原現(xiàn)場(chǎng)(把map還原成初始狀態(tài)initMap)

public static List<Integer> findAnagrams(String s, String p) {List<Integer> result = new ArrayList<Integer>();if (s == null || p == null || p.length() > s.length()) {return result;}Map<Character, Integer> map = new HashMap<Character, Integer>();initMap(p, map);int windowsLen = p.length();//代表左右窗口指針int left = 0;int right = left + windowsLen - 1;while (right < s.length()) {boolean flag = true;List<Character> list = new ArrayList<Character>();for (int i = right; i >= left; i--) {char c = s.charAt(i);Integer count = map.get(c);//i對(duì)應(yīng)的字母不在目標(biāo)串里,因?yàn)閮蓚€(gè)子串的長度一致,故所有包含i上的字母的子串都不滿足條件if (count == null || count == 0) {left = i + 1;right = left + windowsLen - 1;flag = false;break;} else {map.put(c, map.getOrDefault(c, 0) - 1);//把在比較過程中滿足的字母存在list里(因?yàn)檫@里在比較字符串的時(shí)候采用相減的方式而不是==)list.add(c);}}//如果退出時(shí),flag表示整個(gè)窗口的元素都在map里,說明滿足條件if (flag == true) {result.add(left);left++;right = left + windowsLen - 1;}//還原現(xiàn)場(chǎng),讓map的數(shù)據(jù)保持和p的組成一致for (Character c : list) {map.put(c, map.getOrDefault(c, 0) + 1);}}return result;}private static void initMap(String p, Map<Character, Integer> map) {map.clear();for (char c : p.toCharArray()) {map.put(c, map.getOrDefault(c, 0) + 1);}}

?

解法二:

上述代碼比較繁瑣,解法二使用int數(shù)組,直接比較數(shù)組,邏輯上更加清晰

public List<Integer> findAnagrams(String s, String p) {List<Integer> ans = new ArrayList<>();if (s.length() < p.length()) {return ans;}int[] dict = new int[26];//使用26長度的整型數(shù)組來表示給定字符串p的組成for (char c : p.toCharArray()) {dict[c - 'a']++;}//用來記錄滑動(dòng)窗口里的字符串的組成int[] cur = new int[26];for (int i = 0; i < p.length() ; i++) {cur[s.charAt(i) - 'a']++;}for (int i = p.length() ; i < s.length(); i++) {if (isSame(dict, cur)) {ans.add(i - p.length() );}cur[s.charAt(i - p.length() ) - 'a']--;cur[s.charAt(i) - 'a']++;}return ans;}//判斷兩個(gè)int數(shù)組是否一致private boolean isSame(int[] a, int[] b) {for (int i = 0; i < 26; i++) {if (a[i] != b[i]) {return false;}}return true;}

?

?

總結(jié)

以上是生活随笔為你收集整理的滑动窗口算法学习(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。