劍指offer不用加減乘除做加法_劍指offer胡解(一)
阿新 • • 發佈:2021-01-16
技術標籤:劍指offer不用加減乘除做加法
![971b8e1a245957da0fd7b265065a4fc7.png](https://img.796t.com/res/2021/01-16/03/d55aa20c7624fd6e552969583b5513f1.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
}