出現k次與出現1次《演算法很美》

kongbai發表於2020-12-09

題7:出現k次與出現1次

  • 陣列中只有一個數出現了1次,其他的數都出現了k次,請輸出只出現了1次的數。

具體思路:

  1. 建立一個字元二維陣列char[][] kRadix = new char[len][];
  2. 將arr[]的每一個數轉換成三進位制Integer.toString(arr[i],k),並進行翻轉-變為字串-最後整成字元陣列
  3. 同時要將最長的三進位制數長度儲存 if (kRadix[i].length > maxlen) maxlen = kRadix[i].length;
  4. 開闢一個新陣列存放進位制的不進位每一位的和 int[] resArr = new int[maxlen];
  5. 把全部數的三進位制的每一位做不進位和放入陣列resArr[maxlen]中
  6. 最後再用for遍歷resArr[maxlen]%k * (int) (Math.pow(k, i),其實就是%k之後,如果3個相同的基本為0,只有相同數不為三的%k不為0,那麼得出的就是隻出現一次的數。

例子:

10進位制:
297360
3進位制:
210021100
反轉(如果不進行反轉就不能正確的位數進行相加)
200112010
位數相加(3個相同的,要3個相加)
991
每位%3*對應位數k次方(1*3^2)9

public class 出現k次與出現1{
    public static void main(String[] args){
        int[] arr = {2,2,2,9,7,7,7,3,3,3,6,6,6,0,0,0};
        int len = arr.length;
        char[][] kRadix = new char[len][];
        int k = 3;

        int maxlen = 0;
        //轉成k進位制字元陣列
        //對於每個數字
        for (int i = 0; i < len; i++){
            //求每一個數字的三進位制字串並翻轉,然後轉為字元陣列
            kRadix[i] = new StringBuilder(Integer.toString(arr[i],k)).reverse().toString().toCharArray();

            if (kRadix[i].length > maxlen)
                maxlen = kRadix[i].length;
        }
        //不進位加法
        int[] resArr = new int[maxlen];
        for(int i = 0; i < len; i++){
            // 不進位加法
            for(int j = 0; j < maxlen; j++){
                if(j >= kRadix[i].length)
                    resArr[j] += 0;
                else
                    resArr[j] += (kRadix[i][j] - '0');
            }
        }

        int res = 0;
        for (int i = 0; i < maxlen; i++){
            res += (resArr[i] % k) * (int) (Math.pow(k, i));
        }
        System.out.println(res);

    }
}

相關文章