天天一道算法題(第一期)

若是天天作一道算法題,那是否是天天都在進步?javascript

前言

這個活動是從2019年7月中旬開始的,人數不算多,也就幾個好友和好友的好友,過程當中也會有人由於工做的緣故或其餘緣由放棄,或許將來還會有人離開。php

活動的主要形式就是在leetcode刷題,每一個工做日一道題,每週作總結,目前已是第十二期,接下來我會把每期的題作一個總結,因爲我是側重javascript,因此活動中的每道題都是以js語言來實現解題方法。java

活動的規則比較嚴謹,羣裏天天早上10點以前發題,晚上10點審覈,審覈有管理員專門審覈,稱爲打卡,沒有打卡的人,須要發紅包給管理員做爲天天統計費用。羣內不限制編程語言,目前已有Java、php、c等等。git

活動的目的就是培養算法思惟,瞭解常見的算法,好比分治算法、貪心算法、動態優化等等。算法

微信公衆號驚天碼盜同步第一期編程

兩個數組的交集 II

給定兩個數組,編寫一個函數來計算它們的交集。數組

  • 示例 1:
    輸入: nums1 = [1,2,2,1], nums2 = [2,2]
    輸出: [2,2]
    複製代碼
  • 示例 2:
    輸入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    輸出: [4,9]
    複製代碼

題解:微信

  • 替換法
    循環nums1,在循環中判斷nums2中是否存在當前元素,若是存在就push到新的數組,而後在經過splice替換到當前元素,最後排序;編程語言

    執行用時:88ms;內存消耗:35.5MB;函數

    var intersect = function(nums1, nums2) {
        let arr = [];
        nums1.forEach((cur, i) => {
            if (nums2.indexOf(cur) > -1) {
                arr.push(cur)
                nums2.splice(nums2.indexOf(cur), 1, null)
            }
        })
        return arr.sort()
    }; 
    複製代碼
  • 雙指針法
    兩個數組排序,設定兩個爲0的指針,比較兩個指針的元素是否相等,若是相等,元素push到返回值裏,兩個指針同時往前,若是不相等,元素小的指針往前。

    執行用時:84ms;內存消耗:35MB;

    var intersect = function(nums1, nums2) {
        let p1 = 0
        let p2 = 0
        let res = []
        nums1 = nums1.sort((a, b) => a - b)
        nums2 = nums2.sort((a, b) => a - b)
        while(p1 < nums1.length && p2 < nums2.length) {
            if(nums1[p1] == nums2[p2]) {
                res.push(nums1[p1])
                p1++
                p2++
            } else if(nums1[p1] < nums2[p2]) {
                p1++
            } else {
                p2++
            }
        }
        return res
    }
    複製代碼

1比特與2比特字符

有兩種特殊字符。第一種字符能夠用一比特0來表示。第二種字符能夠用兩比特(10 或 11)來表示。

現給一個由若干比特組成的字符串。問最後一個字符是否一定爲一個一比特字符。給定的字符串老是由0結束。

  • 示例 1:
    輸入: bits = [1, 0, 0]
    輸出: True
    解釋: 惟一的編碼方式是一個兩比特字符和一個一比特字符。因此最後一個字符是一比特字符。
    複製代碼
  • 示例 2:
    輸入: bits = [1, 1, 1, 0]
    輸出: False
    解釋: 惟一的編碼方式是兩比特字符和兩比特字符。因此最後一個字符不是一比特字符。
    複製代碼

題解:

  • 正則
    這是我見過最暴力直接的方式,由羣內小夥伴提出的解題方式。

    執行用時:84ms;內存消耗:34.4MB;

    var isOneBitCharacter = function(bits) {
        return /^(10||11||0)*0$/.test(bits.join(""))
    };
    複製代碼
  • 存儲
    經過對象的方式;在循環中判斷,若是遇到0、10或者11等狀況添加到對象的屬性上,這種方式能夠有效的記錄一共出現1比特和2比特出現的次數和順序;最後判斷最後一個比特是1比特仍是2比特。 執行用時:88ms;內存消耗:37.6MB;

    var isOneBitCharacter = function(bits) {
        let obj = {};
        let count = 1;
        bits.forEach((item, i) => {
            if (!obj[count]) obj[count] = [];
            if (obj[count].length >= 2) {count++; obj[count] = []};
            obj[count].push(item)
            if (obj[count][0] == 0 && i!=bits.length-1) count++;
        })
        return obj[count]&&obj[count][0] === 0 ? true : false
    };
    
    //對象結構以下
    //{
    // 1:[0],
    // 2:[1,1],
    // 3:[1,0],
    // ...
    //}
    複製代碼
  • 跳針
    循環,遇1就++,若是++後跳出循環,就返回false,若是還在循環內,當循環到最後一個的時候返回true;

    執行用時:72ms;內存消耗:34.2MB;

    var isOneBitCharacter = function(bits) {
        let bitsSize = bits.length
        for (let i = 0; i < bitsSize; ++i) {
        if (i == bitsSize - 1) return true
        if (bits[i])++i;
        }
        return false;
    };
    複製代碼

二進制求和

給定兩個二進制字符串,返回他們的和(用二進制表示)。

輸入爲非空字符串且只包含數字 1 和 0。

  • 示例 1:
    輸入: a = "11", b = "1"
    輸出: "100"
    複製代碼
  • 示例 2:
    輸入: a = "1010", b = "1011"
    輸出: "10101"
    複製代碼

分析: 面對這道題,不少人立馬想到的是2轉10,而後轉2,可是這會面臨精度丟失的問題,若是解決了精度丟失的問題,那麼也不失爲一個好的解題方法。那麼就只有一種方法那就是逐位相加法。

  • 補位法
    字符串轉數組,而後翻轉數組,取數組最長的length循環,在循環中數組短的自動補0,在循環中相加,判斷相加爲0或1或2的狀況。而後push到新數組中,最後翻轉,轉成字符串。

    執行用時:108ms;內存消耗:35.6MB;(最笨的辦法)

    var addBinary = function(a, b) {
        const alist=a.split('').reverse();
        const blist=b.split('').reverse();
        const arr=[];
        const len=alist.length>blist.length?alist.length:blist.length;
        for (let i = 0; i <= len-1; i++) {
            if (alist[i] != 0 && alist[i] != 1) {
                alist[i] = 0
            }
    
            if (blist[i] != 0 && blist[i] != 1) {
                blist[i] = 0
            }
            
            alist[i] = alist[i] - 0
            blist[i] = blist[i] - 0
    
            if (alist[i] + blist[i] > 1) {
                if (arr[i] == 0) {
                    arr[i] = 1
                } else if (arr[i] == 1) {
                    arr[i] = 1
                    arr.push(1)
                } else {
                    arr[i] = 0
                    arr.push(1)
                }
            }
            if (alist[i] + blist[i] == 1) {
                if (arr[i]) {
                    arr[i] = 0
                    arr.push(1)
                } else {
                    arr[i] = 1
                }
            }
            if (alist[i] + blist[i] == 0) {
                if (arr[i]) {
                    arr[i] = 1
                } else {
                    arr[i] = 0
                }
            }
        }
        return arr.reverse().join('')
    };
    複製代碼
  • 進位拼接法
    與補位法相似,區別就是在進行計算時直接拼接字符串,會獲得一個反向字符,須要最後再進行翻轉;按照位置給結果字符賦值,最後若是有進位,則在前方進行字符串拼接添加進位。

    執行用時:112ms;內存消耗:35.9MB;(性能很差)

    var addBinary = function(a, b) {
        let ans = "";
        let ca = 0;
        for(let i = a.length - 1, j = b.length - 1;i >= 0 || j >= 0; i--, j--) {
            let sum = ca;
            sum += i >= 0 ? parseInt(a[i]) : 0;
            sum += j >= 0 ? parseInt(b[j]) : 0;
            ans += sum % 2;
            ca = Math.floor(sum / 2);
        }
        ans += ca == 1 ? ca : "";
        return ans.split('').reverse().join('');
    }
    複製代碼

兩數之和

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那兩個整數,並返回他們的數組下標。

你能夠假設每種輸入只會對應一個答案。可是,你不能重複利用這個數組中一樣的元素。

  • 示例:
    給定 nums = [2, 7, 11, 15], target = 9
    由於nums[0] + nums[1] = 2 + 7 = 9
    因此返回 [0, 1]
    複製代碼

題解:

  • 雙循環法
    兩層循環,外層取第一元素,內層取相加元素;

    執行用時:164ms;內存消耗:34.6MB;

    var twoSum = function(nums, target) {
        for (let i = 0; i < nums.length; i++) {
            for (let j = i + 1; j < nums.length; j++) {
                if (nums[i] + nums[j] === target) {
                    return [i, j]
                }
            }
        }
    };
    複製代碼
  • 替換法
    複製原數組,循環原數組,防止重複,經過splice替換複製的數組,若是複製數組中存在相加元素,找到索引,便可獲得結果數組。

    執行用時:304ms;內存消耗:36MB;

    var twoSum = function(nums, target) {
        let list = [...nums];
        let arr = []
        nums.forEach((item, i) => {
            list.splice(i, 1, null)
            const sum = target - item;
            if (list.includes(sum)) {
                arr = [i, list.indexOf(sum)].sort()
            }
        })
        return arr
    }
    複製代碼
  • map
    經過新的數據類型Map來實現;

    執行用時:72ms;內存消耗:35.1MB;

    var twoSum = function(nums, target) {
        let map = new Map()
        for (let i = 0; i < nums.length; i++) {
            if (map.has(target - nums[i])) {
                return [map.get(target - nums[i]), i]
            }
            map.set(nums[i], i)
        }
    }
    複製代碼

加一

給定一個由整數組成的非空數組所表示的非負整數,在該數的基礎上加一。

最高位數字存放在數組的首位, 數組中每一個元素只存儲一個數字。

你能夠假設除了整數 0 以外,這個整數不會以零開頭。

  • 示例 1:
    輸入: [1,2,3]
    輸出: [1,2,4]
    解釋: 輸入數組表示數字 123複製代碼
  • 示例 2:
    輸入: [4,3,2,1]
    輸出: [4,3,2,2]
    解釋: 輸入數組表示數字 4321複製代碼

題解:

  • 遞減相加
    循環遞減,在循環中判斷相加是否爲10,若是爲10,就把當前值改成0,下一值加一;

    執行用時:72ms;內存消耗:33.6MB;(性能很差)

    var plusOne = function(digits) {
        for(let i=digits.length-1;i>=0;i--){
            if(i==digits.length-1){
                digits[i]++
            }
            if(digits[i]==10){
                digits[i]=0
                if(i-1<0){
                    digits.unshift(1)
                }else{    
                    digits[i-1]++
                }
            }
        }
        return digits
    };
    複製代碼
  • 條件
    for循環能夠實現的,while也能夠實現;

    執行用時:72ms;內存消耗:34.2MB;(性能很差)

    var plusOne = function(digits) {
        const values = digits.reverse();
        let i = 0;
        values[i] += 1;
        while (true) {
            if (values[i] >= 10) {
                values[i] = 0;
                if (values[i + 1] === undefined) {
                    values[i + 1] = 1;
                    break;
                } else {
                    values[i + 1] += 1
                }
                i++
            } else {
                break;
            }
        }
        return values.reverse()
    };
    複製代碼

第一期結束,雖然堅持很累,加油!

若是你也想利用碎片時間來作這麼一件事情,咱們能夠監督你,二維碼獻上😊

相關文章
相關標籤/搜索