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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java入门算法(贪心篇)丨蓄力计划

發布時間:2023/12/19 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java入门算法(贪心篇)丨蓄力计划 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本專欄已參加蓄力計劃,感謝讀者支持

往期文章

一. Java入門算法(貪心篇)丨蓄力計劃
二. Java入門算法(暴力篇)丨蓄力計劃
三. Java入門算法(排序篇)丨蓄力計劃
四. Java入門算法(遞歸篇)丨蓄力計劃
五. Java入門算法(雙指針篇)丨蓄力計劃
六. Java入門算法(數據結構篇)丨蓄力計劃
七. Java入門算法(滑動窗口篇)丨蓄力計劃


你好,我是Ayingzz,Ayi是我的名字,ing進行時代表我很有動力,zz提醒我按時睡覺 ~

  • 篇幅短小精悍,適合初學者反復咀嚼:此專欄的文章并不是一系列大而全的整理文章,而是一系列簡明扼要的算法入門講解文章,篇幅短而內容精,有利于初學者針對一種或多種算法快速入門。
  • 例題簡單易懂,讓你印象深刻:引入精選LeetCode簡易算法例題,通過生動形象的講解對其思路進行簡明剖析,更容易上手并掌握。
  • 涉及算法種類廣:雙指針、遞歸、排序、貪心、分治、動態規劃、滑動窗口、DFS...各類基礎算法收攬其中。

為什么要學算法?

對于所有的Problems-Solving的過程都可以理解為算法,程序員對算法或多或少都有著一些復雜的情感,為什么一定要學算法?

  • "程序 = 數據結構 + 算法"。這個公式相信已經耳濡目染,目前在各大廠的面試里,對基礎算法的考察的比重逐年增加,只寫會某種語言的工程代碼顯然并不太夠,大部分面試官會優先考慮掌握算法的面試者。在現實開發里,僅使用一些簡單的算法就可以快讀優化各種繁雜的工程代碼,降低時間復雜度與工程運行速度,提升用戶體驗。
  • 對算法的熱愛。作為程序員或多或少對算法都有著某種情感上的執著與偏愛,如果你還是學生,想參與各類的競賽,那么入門算法即是數學建模、軟件開發、算法等各類競賽的敲門磚,選手的動力就是對算法的追求與熱愛,類似的有ACM、藍橋杯等。

專欄思路和內容大綱

基礎部分:

  • 雙指針:巧用雙指針、三指針完成搜索以及其他算法功能;
  • 遞歸:遞歸是算法的敲門磚,大部分算法中都包含遞歸;
  • 排序:基礎入門排序算法,包括選擇、插入、冒泡排序;
  • 貪心:貪心選擇性質、最優子問題講解;
  • 暴力枚舉:常見的暴力枚舉題目講解,鋪墊之后的優化;
  • 數據結構:包括棧、哈希表等。
  • 進階部分:

  • 動態規劃:一張表可以解決的問題,進階版遞歸;
  • DFS與BFS:深度優先搜索、廣度優先搜索;
  • 滑動窗口:利用指針或數組維護特定區間的移動;
  • 高級排序:排序用時短的高級排序,包括快速排序、歸并排序、堆排序等;
  • 分治:分而治之,對原問題的切割子問題求解;
  • 回溯:以深度優先方式配合狀態變量系統搜索問題解的算法。

  • 適宜人群

    • 對算法感興趣的初學者
    • 想加強算法基本功的讀者

    貪心篇

    • 往期文章
    • 為什么要學算法?
    • 專欄思路和內容大綱
    • 適宜人群
    • ~
    • 前言
    • (本篇內容)
      • 花朵 Flower
      • 糖果 Candy
      • 餅干 Cookie
      • 股票 Stock
    • (推薦練習)
      • 加油站
      • 跳躍游戲


    ~

    前言

    貪心算法是入門算法之一,它在百度百科上是這樣解釋的。

    貪心算法的使用條件有兩個:

  • 貪心選擇性質
    一個問題的整體最優解可以通過一系列局部最優解的選擇達到,并且每次的選擇可以依賴以前作出的選擇,但不依賴于后面要作出的選擇,這就是貪心選擇性質。
  • 最優子結構性質
    當一個問題的最優解包含其子問題的最優解時,稱此問題具有最優子結構性質。問題的最優子結構性質是該問題可用貪心法求解的關鍵所在。在實際應用中,至于什么問題具有什么樣的貪心選擇性質是不確定的,需要具體問題具體分析。

  • (本篇內容)

    花朵 Flower

    LeetCode題目描述:605.種花問題(Easy)
    假設有一個很長的花壇,一部分地塊種植了花,另一部分卻沒有。可是,花不能種植在相鄰的地塊上,它們會爭奪水源,兩者都會死去。
    給你一個整數數組 flowerbed 表示花壇,由若干 0 和 1 組成,其中 0 表示沒種植花,1 表示種植了花。另有一個數 n ,能否在不打破種植規則的情況下種入 n 朵花?能則返回 true ,不能則返回 false。

    示例

    輸入:flowerbed = [1,0,0,0,1], n = 1 輸出:true ------------------------------------ 輸入:flowerbed = [1,0,0,0,1], n = 2 輸出:false

    思路:

  • 每次只考慮局部的最優解,也就是考慮具體一個地塊能不能種花;
  • 結合1,花壇從左往右一格一格看過去,若某個格子可以種花,則計入當前可種花總數;若不可以種花,則丟棄,繼續下一格;
  • 能否種花取決于左右格子是否為空地,題目給出的花壇數組中,種花的右側一定是空地,所以我們可以每一次跳2格(i += 2);
  • 基于3的種花條件:當前地塊為空地 且 右側為空地,或者,當前地塊為空地 且 為花壇右邊界;
  • 計數方式:當某個空地的考慮結果是可種花時,將n - 1;
  • 結果判斷:若n為零或者負值,證明此花壇可種花數大于n,返回true,否則返回false。
  • 貪心策略的使用:

    class Solution {public boolean canPlaceFlowers(int[] flowerbed, int n) {int L = flowerbed.length;for (int i = 0; i < L; i += 2) {if (flowerbed[i] == 0) {if (i == L - 1 || flowerbed[i + 1] == 0) {n--;}else{i++;}}}return n <= 0;} }

    糖果 Candy

    LeetCode題目描述:135. 分發糖果(Hard)

    老師想給孩子們分發糖果,有 N 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。

    你需要按照以下要求,幫助老師給這些孩子分發糖果:
    每個孩子至少分配到 1 個糖果。
    評分更高的孩子必須比他兩側的鄰位孩子獲得更多的糖果。
    那么這樣下來,老師至少需要準備多少顆糖果呢?

    示例

    輸入:[1,0,2] 輸出:5 解釋:你可以分別給這三個孩子分發 2、1、2 顆糖果。 ----------------------------------------------------- 輸入:[1,2,2] 輸出:4 解釋:你可以分別給這三個孩子分發 1、2、1 顆糖果。第三個孩子只得到 1 顆糖果,這已滿足上述兩個條件。

    思路:

  • 因為每個孩子至少被分配到1個糖果,所以初始化數組元素為1;
  • 題目的難點是評分更高的孩子必須比他兩側的鄰位孩子獲得更多的糖果,我們可以分開兩次考慮,一次只考慮每個孩子與他右側的孩子的分數關系,一次只考慮每個孩子與他左側孩子的分數關系。按照關系,修改每個孩子得到的糖果數量。
  • 需要注意的是,因為第一次從左往右遍歷時數組已經修改,所以在第二次從右往左的遍歷里,不僅要考慮每個孩子與他左側孩子的分數關系,還要考慮兩個孩子已經得到的糖果數量關系。
  • 最后,只需將修改的數組做累加,即可求出至少需要準備的糖果數量。
  • 貪心策略的使用:

    class Solution {public static int candy(int[] ratings) {int[] candy = new int[ratings.length];// 每個孩子至少有一個糖果,初始化數組元素為1Arrays.fill(candy, 1);// 從左往右,每次考慮左邊孩子評分比右邊孩子評分高的情況for (int i = 0; i < ratings.length - 1; ++i) {if (ratings[i + 1] > ratings[i]) {candy[i + 1] = candy[i] + 1;}}// 從右往左,每次考慮右邊孩子評分比左邊孩子評分高的情況for (int i = ratings.length - 1; i > 0; --i) {if (ratings[i - 1] > ratings[i] && candy[i - 1] <= candy[i]) {candy[i - 1] = candy[i] + 1;} }// 答案數組求和int min_candy_sum = 0;for (int x : candy) { min_candy_sum += x;}return min_candy_sum;} }

    餅干 Cookie

    LeetCode題目描述:455. 分發餅干(Easy)
    假設你是一位很棒的家長,想要給你的孩子們一些小餅干。但是,每個孩子最多只能給一塊餅干。
  • 對每個孩子 i,都有一個胃口值 g [ i ],這是能讓孩子們滿足胃口的餅干的最小尺寸;
  • 每塊餅干 j,都有一個尺寸 s [ j ] 。如果 s [ j ] >= g [ i ],我們可以將這個餅干 j 分配給孩子 i ,這個孩子會得到滿足。
  • 你的目標是盡可能滿足越多數量的孩子,并輸出這個最大數值。
  • 示例

    輸入: g = [1,2,3], s = [1,1] 輸出: 1 解釋: 你有三個孩子和兩塊小餅干,3個孩子的胃口值分別是:1,2,3。 雖然你有兩塊小餅干,由于他們的尺寸都是1,你只能讓胃口值是1的孩子滿足。 所以你應該輸出1。 --------------------------------------------------------------------- 輸入: g = [1,2], s = [1,2,3] 輸出: 2 解釋: 你有兩個孩子和三塊小餅干,2個孩子的胃口值分別是1,2。 你擁有的餅干數量和尺寸都足以讓所有孩子滿足。 所以你應該輸出2.

    思路:

  • 貪心策略下,應先考慮胃口值最小的孩子,并把大于等于這個孩子饑餓度的、且大小最小的餅干分配給這個孩子。所以我們需要先將兩個數組升序排序。
  • 每次由當前孩子選擇餅干,若能滿足這個孩子,則輪到下一個孩子選擇;不能滿足,則還是這個孩子選擇餅干,且考慮下一個大小更大的餅干。(餅干不能重復選擇)
  • class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int child = 0, cookie = 0;while (child < g.length && cookie < s.length) {// 如果能滿足,則輪到下一個孩子選餅干if (g[child] <= s[cookie]) { ++child;}++cookie;}// 輪流了多少個孩子,就是滿足了的孩子的數量return child;} }

    股票 Stock

    LeetCode題目描述:122. 買賣股票的最佳時機 ll(Easy)
    給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。設計一個算法來計算你所能獲取的最大利潤,你可以多次買賣這一支股票。

    *注:你必須在再次購買前出售掉之前的股票

    示例

    輸入: [7,1,5,3,6,4] 輸出: 7

    解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5 -1 = 4 。隨后,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6 -3 = 3 。

    輸入: [1,2,3,4,5] 輸出: 4

    解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。

    思路:

  • 我們先只尋找買入的時間(也就是極小值 / 上升沿),找到后買入;
  • 再只尋找賣出的時間(也就是極大值 / 下降沿),找到后賣出。
  • 貪心策略的使用:

    class Solution {public int maxProfit(int[] prices) {int ans = 0;int n = prices.length;if (n == 1) {return 0;}for (int i = 0; i < n - 1; ++i) {// 尋找極小值while (i < n - 1 && prices[i] > prices[i + 1]) {++i;}// 買入ans -= prices[i];// 尋找極大值while (i < n - 1 && prices[i] < prices[i + 1]) {++i;}// 賣出ans += prices[i];}return ans;} }

    (推薦練習)

    \

    加油站

    • 在一條環路上有 N 個加油站,其中第 i 個加油站有汽油 gas[i] 升。
    • 你有一輛油箱容量無限的的汽車,從第 i 個加油站開往第 i+1 個加油站需要消耗汽油 cost[i] 升。你從其中的一個加油站出發,開始時油箱為空。
    • 如果你可以繞環路行駛一周,則返回出發時加油站的編號,否則返回 -1。

    跳躍游戲

    • 給定一個非負整數數組 nums ,你最初位于數組的 第一個下標 。
    • 數組中的每個元素代表你在該位置可以跳躍的最大長度。
    • 判斷你是否能夠到達最后一個下標。

    /


    總的來說,具體問題具體分析,只要確定一個問題的局部最優解可以導致問題的整體最優解,那么即可以考慮選擇貪心策略、分治或動態規劃(下篇)解決。

    若有不當歡迎指正。本專欄持續周更,預計7月結束

    總結

    以上是生活随笔為你收集整理的Java入门算法(贪心篇)丨蓄力计划的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。