06-彩磚拼色-等差數列-01串-逆序n次-機器人走位-紙牌博弈

年輕即出發...

簡書http://www.lxweimin.com/u/7110a2ba6f9e

知乎https://www.zhihu.com/people/zqtao23/posts

GitHub源碼https://github.com/zqtao2332

個人網站http://www.zqtaotao.cn/ (停止維護更新內容)

QQ交流群:606939954

? 咆哮怪獸一枚...嗷嗷嗷...趁你現在還有時間,盡你自己最大的努力。努力做成你最想做的那件事,成為你最想成為的那種人,過著你最想過的那種生活。也許我們始終都只是一個小人物,但這并不妨礙我們選擇用什么樣的方式活下去,這個世界永遠比你想的要更精彩。

最后:喜歡編程,對生活充滿激情



本節內容預告

實例1:彩磚拼色

實例2:等差數列

實例3:01串

實例4:逆序n次

實例5:機器人走位

實例6:紙牌博弈



實例1:彩磚拼色

小易有一些彩色的磚塊。每種顏色由一個大寫字母表示。各個顏色磚塊看起來都完全一樣。

現在有一個給定的字符串s,s中每個字符代表小易的某個磚塊的顏色。

小易想把他所有的磚塊排成一行

如果最多存在一對不同顏色的相鄰磚塊,那么這行磚塊就很漂亮的。

請你幫助小易計算有多少種方式將他所有磚塊排成漂亮的一行。(如果兩種方式所對應的磚塊顏色序列是相同的,那么認為這兩種方式是一樣的。)

例如: s= "ABAB",那么小易有六種排列的結果:'AABB", "ABAB", "ABBA", "ВAAВ", " ВАВА ", " ВВАА"其中只有"AABB"和"BBAA"滿足最多只有一對不同顏色的相鄰磚塊。

信息提取:

1、最多存在一對不同顏色的相鄰磚塊

顏色超過2中不滿足

2、相鄰磚塊成對

N 個磚塊,有 N-1對

3、篩選條件

1、顏色只有一種,返回1
2、顏色只有兩種,返回2
3、顏色超過2,返回0
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Code_15_ColorBrik {

    public static int getColorBrik(String str) {
        if (str == null || str.length() == 0) {
            return 0;
        }
        Set<Character> set = new HashSet<>();

        int res = 0;
        for (char c : str.toCharArray()) {
            if (!set.contains(c)){
                set.add(c);
                res++;
            }
        }
        return res > 2 ? 0 : res;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        System.out.println(getColorBrik(str));
        in.close();
    }
}

實例2:等差數列

如果一個數列S滿足對于所有的合法的i,都有S[i + 1] = S[i] +d,這里的d也可以是負數和零,我們就稱數列S為等差數列。

小易現在有一個長度為n的數列x,小易想把x變為一個等差數列。

小易允許在數列上做交換任意兩個位置的數值的操作,并且交換操作允許交換多次。

但是有些數列通過交換還是不能變成等差數列,小易需要判別一個數列是否能通過交換操作變成等差數列

輸入描述:

輸入包括兩行,

第一行包含整數n(2 <n < 50),即數列的長度。

第二行n個元素x[i] (0 <x[i] < 1000),即數列中的每個整數。

思路:

利用等差數列求和公式

2_1_等差數列求和公式.png

遍歷一遍數組求出幾個數據

sum 、n

同時找到最小值和次小值,算出 d

代入公式查看是否滿足等差數列的求和公式

import java.util.Scanner;

/**
 * @description: 等差數列
 */
public class Code_16_ArithmeticSequence {

    public static boolean isArithmeticSequence(int[] arr) {
        if (arr == null || arr.length == 0) {
            return false;
        }

        int sum = 0;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            min = Math.min(min, arr[i]);
        }

        int n = arr.length;
        if ((2 * (sum - min * n)) % (n * (n - 1)) == 0) { // d 可以為0 或是整數,%后為0
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = in.nextInt();
        }
        if (isArithmeticSequence(arr))
            System.out.println("Possible");
        else
            System.out.println("Impossible");
        in.close();
    }
}

實例3:01串

如果一個01串任意兩個相鄰位置的字符都是不一樣的,我們就叫這個01串為交錯01串。

例如: "1","10101","0101010"都是交錯01串。

小易現在有一個01串s,小易想找出一個最長的連續子串,并且這個子串是一個交錯01串。小易需要你幫幫忙求出最長的這樣的子串的長度是多少。

輸入描述:

輸入包括字符串s,

s的長度length(1 < length < 50),字符串中只包含'0'和'1

題目三擴展小易想找出一個最長的連續子串,并且這個子串是0和1數量相等的。該怎么做?

思路:

維護兩個變量,max:記錄最大長度, len: 記錄當前01串長度

比較 i 位置和 i-1位置,相同 len=0,不同len++

   public static int max01Str(String str) {
        if (str == null || str.length() == 0) return 0;

        int max = 1;
        int len = 1;
        for (int i = 0; i < str.length(); i++) {
            len++;
            if (str.charAt(i) == str.charAt(i-1)){
                len = 1;
            }
            max = Math.max(max, len);
        }
        return max;
    }

擴展思路:

再次之前先回憶一下另外一道題

給定數組arr[] ,求子數組累加滿足給定值k的最長子數組長度。

http://www.lxweimin.com/p/431e9f9f7b74

此題,以某個位置為結尾的子數組,累加和為定值 k
    public static int maxSubArrLen(int[] arr, int k) {
        if (arr == null || arr.length == 0) return 0;

        int len = 0;
        int sum = 0;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1); // 處理第一位等于 k 的情況
        /*
             6 1 2 3  k = 6
             上來 sum = 6
             sum - k = 0;
             len = i - map.get(0) 但是現在不存在map.get(0) 這樣len返回的結果是0,而不是 1
         */
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            if (map.containsKey(sum - k)) {
                len = Math.max(len, i - map.get(sum - k));
            }

            if (!map.containsKey(sum)) {
                map.put(sum, i);
            }
        }
        return len;
    }

現在再看擴展,將題目中的0全部置為 -1 ,那么原問題就變成了求 滿足子數組累加和為0 的最長子數組。

public static int max01Str2(String str) {
    if (str == null || str.length() == 0) return 0;

    HashMap<Integer, Integer> map = new HashMap<>();
    map.put(0, -1);

    int sum = 0;
    int len = 0;
    int k = 0; // 求滿足子數組累加等于0 的子數組長度

    for (int i = 0; i < str.length(); i++) {
        int cNum = (int) str.charAt(i) - '0';
        sum += cNum;
        if (map.containsKey(sum - k)){
            len = Math.max(len, i - map.get(sum - k));
        }
        if (!map.containsKey(sum - k)){ // 不存在就添加
            map.put(sum, i);
        }
    }
    return len;
}

實例4:逆序n次

小易有一個長度為n的整數序列, a_1. .., an。然后考慮在一個空序列b上進行n次以下操作:1、將ai放入b序列的末尾2、逆置b序列小易需要你計算輸出操作n次之后的b序列。

輸入描述:輸入包括兩行,第一行包括一個整數n(2 第二行包括n個整數ai(1 < a_i < 10~9),即序列a中的每個整數,以空格分割

思路:雙端隊列

4_1_規律.png
維護一個雙端隊列
每次添加都是先添加右邊在添加左邊

查看最后一次是添加在右邊還是添加在左邊,右邊,逆序,左邊,不逆序

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;

public class Code_18_NReverse {

    public static int[] reverse(int[] arr) {
        Deque<Integer> deque = new LinkedList<>();// 雙端隊列
        boolean convert = false; //  標記是否需要逆序
        for (int i = 0; i < arr.length; i++) {
            if (convert) {
                deque.addLast(arr[i]);
            } else { // 不需要轉換就加入雙端隊列的尾部
                deque.addFirst(arr[i]);
            }
            convert = !convert;
        }

        // 查看結果是否需要逆序
        int i = 0;
        if (convert) {
            while (!deque.isEmpty())
                arr[i++] = deque.pollFirst();
        } else {
            while (!deque.isEmpty()) {
                arr[i++] = deque.pollLast();
            }
        }
        return arr;
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6};
        reverse(arr);
        System.out.println(Arrays.toString(arr));
    }
}

實例5:機器人走位

一排有N個位置,一個機器人在最開始停留在P位置上,如果 p==0位置,下一分鐘機器人一定向右移動到1位置;如果p==N-1,下一分鐘機器人一定向左移動到N-2位置。如果P在0和N-1之間,下一分鐘機器人一定會向左或者向右移動。求K分鐘的時候,機器人到達位置有多少種走法。函數為: int f(int N, int P, int K, int T),返回值為走法的數量

public class Code_19_MachineRoad {

    // 暴力嘗試
    public static int f1(int N, int P, int K, int T) {
        if (N < 2 || P < 0 || K < 1 || T < 0 || P >= N || T >= N) {
            return 0; // 越界處理
        }
        if (K == 1) { // 一分鐘,一種或沒有
            return T == P ? 1 : 0;
        }

        // 兩端位置
        if (T == 0) {
            return f1(N, P, K - 1, 1);
        }
        if (T == N - 1) {
            return f1(N, P, K - 1, T - 1);
        }
        // 普遍位置
        return f1(N, P, K - 1, T - 1) + f1(N, P, K - 1, T + 1);
    }

    // 動態規劃 一維表
    public static int f2(int N, int P, int K, int T) {
        if (N < 2 || P < 0 || K < 1 || T < 0 || P >= N || T >= N) {
            return 0;
        }
        int[][] dp = new int[K][N];
        dp[0][P] = 1;
        for (int i = 1; i < K; i++) {
            dp[i][0] = dp[i - 1][1];
            dp[i][N - 1] = dp[i - 1][N - 2];
            for (int j = 1; j < N - 1; j++) {
                dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];
            }
        }
        return dp[K - 1][T];
    }

    // 動態規劃 二維表
    public static int f3(int N, int P, int K, int T) {
        if (N < 2 || P < 0 || K < 1 || T < 0 || P >= N || T >= N) {
            return 0;
        }
        int[] dp = new int[N];
        dp[P] = 1;
        int pre = 0;
        int tmp = 0;
        for (int i = 1; i < K; i++) {
            pre = dp[0];
            dp[0] = dp[1];
            for (int j = 1; j < N - 1; j++) {
                tmp = dp[j];
                dp[j] = pre + dp[j + 1];
                pre = tmp;
            }
            dp[N - 1] = pre;
        }
        return dp[T];
    }

    public static void main(String[] args) {
        for (int i = 0; i < 300; i++) {
            int N = (int) (Math.random() * 5) + 5;
            int P = (int) (Math.random() * N);
            int K = (int) (Math.random() * 10) + 2;
            int T = (int) (Math.random() * N);
            int res1 = f1(N, P, K, T);
            int res2 = f2(N, P, K, T);
            int res3 = f3(N, P, K, T);
            if (res1 != res2 || res1 != res3) {
                System.out.println("Fuck man!");
                break;
            }
        }
    }
}

實例6:紙牌博弈

排成一條線的紙牌博弈問題【題目】給定一個整型數組arr,代表數值不同的紙牌排成一條線。玩家 A和玩家B依次拿走每張紙牌,規定玩家A先拿,玩家B后拿,但是每個玩家每次只能拿走最左或最右的紙牌,玩家A和玩家B都絕頂聰明。請返回最后獲勝者的分數。【舉例】arr=[1, 2, 100, 4]。開始時玩家A只能拿走1或4。如果玩家A拿走1,則排列變為 2, 100, 4],接下來玩家B可以拿走2或4,然后繼續輪到玩家A。

public class Code_20_SelectedCards {

    // 暴力嘗試
    public static int win1(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1));
    }

    public static int f(int[] arr, int i, int j) {
        if (i == j) {
            return arr[i];
        }
        return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
    }

    public static int s(int[] arr, int i, int j) {
        if (i == j) {
            return 0;
        }
        return Math.min(f(arr, i + 1, j), f(arr, i, j - 1));
    }

    // 單獨調用自己的暴力嘗試
    public static int process(int[] arr, int i, int j) {
        if (i == j) {
            return arr[i];
        }
        if (i == j - 1) {
            return Math.max(arr[i], arr[j]);
        }
        return Math.max(arr[i] + Math.min(process(arr, i + 2, j), process(arr, i + 1, j - 1)),
                arr[j] + Math.min(process(arr, i + 1, j - 1), process(arr, i, j - 2))
        );
    }

    // 動態規劃
    public static int win2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        int[][] f = new int[arr.length][arr.length];
        int[][] s = new int[arr.length][arr.length];
        for (int j = 0; j < arr.length; j++) {
            f[j][j] = arr[j];
            for (int i = j - 1; i >= 0; i--) {
                f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);
                s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);
            }
        }
        return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);
    }

    public static void main(String[] args) {
        int[] arr = { 1, 9, 1 };
        System.out.println(win1(arr));
        System.out.println(win2(arr));

    }
}

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容