1. 程式人生 > 其它 >劍指offer不用加減乘除做加法_劍指offer胡解(一)

劍指offer不用加減乘除做加法_劍指offer胡解(一)

技術標籤:劍指offer不用加減乘除做加法

971b8e1a245957da0fd7b265065a4fc7.png
建完部落格發現一時沒啥寫的,轉載灌水也不合適,想起來在牛客網看到的《劍指offer66題》基本都是 c 跟 Java,寫一份 JS 的好了。作為一個小白沒啥效能追求,能寫出來就行。todo是參看題解獲得的思路,日後自己寫一下。
也不知道啥時候能寫完,66題就拆6篇寫。

1.二維陣列中的查詢

題目描述
在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
遍歷每個一維陣列,一維陣列內用二分查詢 todo

從左下 / 右上找:左下為該列最大該行最小
二維折半查詢:二維陣列分為上下左右四個邊界 top, bottom, left, right, 對 top 折半,將二維陣列位於終止點E右邊的矩形Rr排除,終止點E小於其右邊相鄰的元素E+1,E+1是右邊矩形Rr的最小元素(左上元素),上下左右依次
function Find(target, array) {
    // write code here

    function FindInline(array) {
        if (array[0] == target) {
            x = 0
            return true
        }
        if (array[w - 1] == target) {
            x = w
            return true
        }
        while (x != rx) {
            switch (true) {
                case array[x - 1] > target:
                    rx = x
                    x = Math.ceil((lx + rx) / 2)
                    break
                case array[x - 1] < target:
                    lx = x
                    x = Math.ceil((lx + rx) / 2)
                    break
                default:
                    return true
            }
        }
        lx = 1
        rx = w
        x = Math.ceil((lx + rx) / 2)
        return false
    }
    let w = array[0].length
    let lx = 1
    let rx = w
    let x = Math.ceil((lx + rx) / 2)

    if (!array.length || !w) return false
    for (let i = 0; i < array.length; i++) {
        if (FindInline(array[i])) return true
  }

    return false
}

2.替換空格

題目描述
請實現一個函式,將一個字串中的每個空格替換成“%20”。例如,當字串為We Are Happy.則經過替換之後的字串為We%20Are%20Happy。
差點就想用 .replace ,不行啊大兄弟,要自己實現一個
function replaceSpace(str) {
    // write code here
    let arr = str.split('')
    let k
    for (k in arr) {
        arr[k] == ' ' ? (arr[k] = '%20') : 0
    }
    return arr.join('')
}

3.翻轉單詞順序列

題目描述
牛客最近來了一個新員工Fish,每天早晨總是會拿著一本英文雜誌,寫些句子在本子上。同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。後來才意識到,這傢伙原來把句子單詞的順序翻轉了,正確的句子應該是“I am a student.”。Cat對一一的翻轉這些單詞順序可不在行,你能幫助他麼?
JS 一句話解決(這樣是拿不到 offer 的 = =,下次再改吧)
function ReverseSentence(str)
{
    // write code here
    return str
    .split(" ")
    .reverse()
    .join(" ")
}

4.左旋轉字串

題目描述
組合語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字串模擬這個指令的運算結果。對於一個給定的字元序列S,請你把其迴圈左移K位後的序列輸出。例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!
拆成陣列 .shift.push 模擬即可
function LeftRotateString(str, n)
{
    // write code here
    if(!str) return ''

    let strA = str.split('')
    for (let i = 0; i < n; i++) {
        strA.push(strA.shift())
    }
    return strA.join('')
}

5.撲克牌順子

題目描述
LL今天心情特別好,因為他去買了一副撲克牌,發現裡面居然有2個大王,2個小王(一副牌原本是54張^_^)...他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!!“紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子.....LL不高興了,他想了想,決定大小 王可以看成任何數字,並且A看作1,J為11,Q為12,K為13。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。LL決定去買體育彩票啦。 現在,要求你使用這幅牌模擬上面的過程,然後告訴我們LL的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。為了方便起見,你可以認為大小王是0。
排序後統計 Joker (0) 的個數並從陣列剔除 依次確認差是否為1 不為1則使用 Joker 填補,差增加1,剩餘 Joker 個數減1 但凡不滿足條件則 flag = false
function IsContinuous(numbers) {
    // write code here
    if (!numbers.length) return false
    let flag = true
    let joker = 0

    let [...num] = numbers.sort()
    numbers.reduce(function(pv, cv) {
        if (cv == 0) {
            num.shift()
            joker++
        }
        return cv
    }, 0)

    num.reduce(function(pv, cv) {
        if (pv + 1 == cv) return cv

        let i = 1
        while (joker > 0) {
            joker--
            i++
            if (pv + i == cv) return cv
        }
        flag = false
        return cv
    })

    return flag
}

6.孩子們的遊戲(圓圈中最後剩下的數)

題目描述
每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成一個大圈。然後,他隨機指定一個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下一個小朋友開始,繼續0...m-1報數....這樣下去....直到剩下最後一個小朋友,可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!^_^)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)
如果沒有小朋友,請返回-1
產生包含小朋友序號的陣列 .splice 模擬出圈 使用 % 解決 m > n 的情況
function LastRemaining_Solution(n, m) {
    // write code here
    if (n == 0) return -1

    let arr = Array.from({ length: n }, (v, i) => i)
    let ctr = m - 1

    while (arr.length > 1) {
        ctr = ctr % arr.length
        arr.splice(ctr, 1)
        ctr += m - 1
    }

    return arr[0]
}

7.求1+2+3+...+n

題目描述
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
實際 .reduce 也是用迴圈了,算投機吧 todo
看了下題解有用位運算子實現乘法的,實在是力所不能及
或者使用遞迴實現迴圈,用 && 短路或者 try{}catch{} 實現迴圈終止
function Sum_Solution(n) {
    // write code here
    let arr = Array.from({ length: n }, (v, i) => i + 1)
    return arr.reduce((pv, cv) => {
        return pv + cv
    })
}

8.不用加減乘除做加法

題目描述
寫一個函式,求兩個整數之和,要求在函式體內不得使用+、-、*、/四則運算子號。
使用陣列長度記錄數字絕對值,通過 .concat .splice 完成加減 ++ -- 情況下相加即可, +— 需判斷絕對值大小
PS: 0分做法,大數計算直接崩。
function Add(num1, num2) {
    // write code here
    num1 > num2 ? 0 : ([num1, num2] = [num2, num1])

    let flag1 = num1 >= 0
    let flag2 = num2 >= 0

    num1 = Math.abs(num1)
    num2 = Math.abs(num2)

    let l1 = new Array(num1).concat(new Array(num2)).length

    if (flag2) return l1

    if (flag1) {
        if (num1 > num2) return new Array(num1).splice(num2).length

        return -new Array(num2).splice(num1).length
    }

    return -l1
}

9.把字串轉換成整數

題目描述
將一個字串轉換成一個整數,要求不能使用字串轉換整數的庫函式。 數值為0或者字串不是一個合法的數值則返回0
拿不到 offer 做法+1,日後再改吧 n < -2147483648||n>2147483647 這個條件是 int 型別取值範圍,出題人估計只考慮了強型別語言。 JS 沒有這個限制
正經做應該 .split('') 拆分以後,每位乘10。
PS:看題解也是一大片的 int(s) 一步到位。。。
function StrToInt(str)
{
    // write code here
    if (!/^[+-]?d+$/.test(str)) return 0
    let n = parseInt(str,10)
    if (n < -2147483648||n>2147483647) return 0
    return n
}

10.陣列中重複的數字

題目描述
在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。
用一個物件記錄出現過的數字,或者用原陣列記錄
PS: 強行用了一下 in,直接 if(count[numbers[i]]) 就行(這個運算子存在感好低呀)
function duplicate(numbers, duplication) {
    // write code here
    //這裡要特別注意~找到任意重複的一個值並賦值到duplication[0]
    //函式返回True/False
    let count = {}
    let n = numbers.length
    let index = 0
    for (i = 0; i < n; i++) {
        index = numbers[i]
        index > n ? (index -= n) : 0
        if (numbers[index] > n) {
            duplication[0] = index
            return true
        }
        numbers[index] += n
        // if (count[numbers[i]]) {
        //  duplication[0] = numbers[i]
        //  return true
        // }
        // count[numbers[i]] = 1
    }
    return false
}

11.構建乘積陣列

題目描述
給定一個數組A[0,1,...,n-1],請構建一個數組B[0,1,...,n-1],其中B中的元素B[i]=A[0] A[1]... A[i-1]A[i+1] ...A[n-1]。不能使用除法。
考慮到 i-1 不能小於0,題目應意為
為界拆分為兩個積
function multiply(array) {
    // write code here
    let al = array.length
    let arrB = []
    let arrC = [1]
    let arrD = []

    arrD[al - 1] = 1

    for (let i = 1; i < al; i++) {
        arrC[i] = arrC[i - 1] * array[i - 1]
        arrD[al - i - 1] = arrD[al - i] * array[al - i]
    }

    for (let i = 0; i < al; i++) {
        arrB[i] = arrC[i] * arrD[i]
    }

    return arrB
}