1. 程式人生 > 實用技巧 >Leetcode(easy Greedy)

Leetcode(easy Greedy)

Leetcode(easy Greedy)

leetcode 貪心演算法的簡單題目

122. 買賣股票的最佳時機 II

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。設計一個演算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交易(多次買賣一支股票)。注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

class Solution {
    public int maxProfit(int[] prices) {
        // 貪心演算法:只要今天買明天賺就買入
        // profit用來記錄前後兩天的差值
        int res = 0;
        int[] profit = new int[prices.length - 1];
        for(int i =0;i<prices.length-1;i++) profit[i] = prices[i+1] - prices[i];
        for(int n:profit) if(n>0) res+=n;
        return res;
    }
}

455. 分發餅乾

class Solution {
    public int findContentChildren(int[] grid, int[] size) {
        if (grid == null || size == null) return 0;
        Arrays.sort(grid);
        Arrays.sort(size);
        int gi = 0, si = 0;
        while (gi < grid.length && si < size.length) {
            if (grid[gi] <= size[si]) {
                gi++;
            }
            si++;
        }
        return gi;
    }

}

860 檸檬水找零

class Solution {
    public boolean lemonadeChange(int[] bills) {
        if(bills == null || bills.length==0) return true;
        int[] money = new int[3];
        for(int n:bills){
            if(n==5) money[0]++;
            if(n==10){
                if(money[0]<1){
                    return false;
                }else{
                    money[0]--;
                    money[1]++;
                }
            }
            if(n==20){
                if(money[0]>0 && money[1]>0){
                    money[0]-=1;
                    money[1]-=1;
                    money[2]++;
                }
                else if(money[0]>2){
                    money[0]-=3;
                    money[2]++;
                }
                else{
                    return false;
                }
            }
        }
        return true;

    }
}

874. 模擬行走機器人

class Solution {
    public int robotSim(int[] commands, int[][] obstacles) {
        //direction表當前朝向,0123 表 北東南西
        int ans = 0,direction = 0,x = 0,y = 0;
        //每個朝向上的資料變化,比如朝北時取Direction[0]  ->   {0,1}
        //那麼x軸的變化為x+0,y軸變化為y+1;
        int[][] Direction = {{0,1},{1,0},{0,-1},{-1,0}};

        HashSet<String> set = new HashSet<>();
        //將所有障礙物座標組合成字串存入set中方便查詢
        for (int[] arr : obstacles) set.add(arr[0]+","+arr[1]);

        for (int com : commands){
            //定義下一步的座標
            int next_x = 0,next_y = 0;
            //當命令為前進,開始移動
            if (com >= 0 ){
                for(int i = 0; i < com; i++){
                    //取得下一步的座標
                    next_x = x + Direction[direction][0];
                    next_y = y + Direction[direction][1];
                    //若下一步有障礙物,結束當前命令,跳至下一命令
                    if(set.contains(next_x+","+next_y)) break;
                    //否則更新座標與最遠距離
                    x = next_x;
                    y = next_y;
                    ans = Math.max(ans, x*x + y*y);
                }
            }else{
                //改變朝向
                direction = com == -1 ? (direction + 1) % 4 : (direction + 3) % 4;
            }
        }
        return ans;
    }
}

944. 刪列造序

class Solution {
    public int minDeletionSize(String[] A) {
        int ans = 0;
        for (int c = 0; c < A[0].length(); ++c)
            for (int r = 0; r < A.length - 1; ++r)
                if (A[r].charAt(c) > A[r+1].charAt(c)) {
                    ans++;
                    break;
                }

        return ans;
    }
}

1005. K 次取反後最大化的陣列和

class Solution {
    public int largestSumAfterKNegations(int[] A, int K) {
        Arrays.sort(A);
        int m=0;
        for(int n:A) if(n<0) m++;
        int flag =0;
        for(int n:A) if(n==0) flag=1;
        int i = 0;
        while(m>0&&K>0){
            A[i]=-A[i];
            m--;
            i++;
            K--;
        }
        int res = 0;
        if(K==0||flag==1) for(int n:A) res+=n;
        else{
            Arrays.sort(A);
            while(K>0){
                A[0]=-A[0];
                K--;
            } 
            for(int n:A) res+=n;
        }
        return res;

    }
}

1046. 最後一塊石頭的重量

有一堆石頭,每塊石頭的重量都是正整數。
每一回合,從中選出兩塊 最重的 石頭,然後將它們一起粉碎。假設石頭的重量分別為 x 和 y,且 x <= y。那麼粉碎的可能結果如下:
如果 x == y,那麼兩塊石頭都會被完全粉碎;
如果 x != y,那麼重量為 x 的石頭將會完全粉碎,而重量為 y 的石頭新重量為 y-x。
最後,最多隻會剩下一塊石頭。返回此石頭的重量。如果沒有石頭剩下,就返回 0。

class Solution {
    public int lastStoneWeight(int[] stones) {
        // myidea : 利用一個優先佇列,每次都去敲兩塊最大的石頭,敲碎的石頭再重新進入優先佇列也就是大頂堆
        Queue<Integer> queue = new PriorityQueue<>((o1, o2) -> (o2 - o1));
        for(int num:stones) queue.offer(num);
        while(queue.size()>1) queue.offer(Math.abs(queue.poll()-queue.poll()));
        int res =0;
        res = queue.poll();
        return res;
    }
}

1217. 玩籌碼

數軸上放置了一些籌碼,每個籌碼的位置存在陣列 chips 當中。
你可以對 任何籌碼 執行下面兩種操作之一(不限操作次數,0 次也可以):
將第 i 個籌碼向左或者右移動 2 個單位,代價為 0。
將第 i 個籌碼向左或者右移動 1 個單位,代價為 1。
最開始的時候,同一位置上也可能放著兩個或者更多的籌碼。
返回將所有籌碼移動到同一位置(任意位置)上所需要的最小代價。

class Solution {
    public int minCostToMoveChips(int[] position) {
        // myieda:偶數位置全部移動到偶數位置的代價是0,同理奇數位置全部移動到同一奇數位置的代價也為0,最終的結果就是奇數位置的元素和偶數位置的元素較小的那一個
        int[] pos = new int[2];
        for(int num:position) if(num%2==1) pos[1]++; else pos[0]++;
        return Math.min(pos[0],pos[1]);
    }
}

1221. 分割平衡字串

在一個「平衡字串」中,'L' 和 'R' 字元的數量是相同的。
給出一個平衡字串 s,請你將它分割成儘可能多的平衡字串。
返回可以通過分割得到的平衡字串的最大數量。

class Solution {
    public int balancedStringSplit(String s) {
        // myidea 貪心 記錄R與L之間的差值,若為0,res++
        int res = 0;
        int flag = 0;
        for(char c:s.toCharArray()){
            if(c=='R') flag++;
            if(c=='L') flag--;
            if(flag==0) res++;
        }
        return res;
    }
}

1403. 非遞增順序的最小子序列

class Solution {
    public List<Integer> minSubsequence(int[] nums) {
        Arrays.sort(nums);
        List<Integer> list = new ArrayList<>();
        int sum = 0;
        int temp = 0;
        for(int i:nums) sum+=i;
        for(int i=nums.length-1;i>-1;i--){
            temp +=nums[i];
            list.add(nums[i]);
            if(temp>sum-temp) break;
        }
        for(int i:list) System.out.println(i);
        return list;
        
    }
}

1518. 換酒問題

class Solution {
    public int numWaterBottles(int numBottles, int numExchange) {
        int ans = numBottles;
        while(numBottles!=0){
            ans+=helper(numBottles,numExchange)[0];
            numBottles=helper(numBottles,numExchange)[1]/numExchange;;
        }
        return ans;
    }

    public int[] helper(int numOfNullBottles,int numExchange){
        int res = 0;
        int[] temp = new int[2];
        while(numOfNullBottles/numExchange!=0){
            res+=numOfNullBottles/numExchange;
            numOfNullBottles=numOfNullBottles%numExchange+numOfNullBottles/numExchange;
        }
        temp[0] = res;
        temp[1] = numOfNullBottles; 
        return temp;
    }
}