【JavaScript】前端算法題 40道題+解析
前言
最近練習(xí)了一些前端算法題,現(xiàn)在做個總結(jié),以下題目都是個人寫法,并不是標(biāo)準(zhǔn)答案,如有錯誤歡迎指出,有對某道題有新的想法的友友也可以在評論區(qū)發(fā)表想法,互相學(xué)習(xí)??
題目
題目一: 二維數(shù)組中的查找: 在一個二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數(shù),輸入這樣的一個二維數(shù)組和一個整數(shù),判斷數(shù)組中是否含有該整數(shù)。
function sortList(array, num) {
// 解法一.循環(huán)indexOf查詢 有返回下標(biāo),沒有則返回-1
// for (let i = 0; i < array.length; i++) {
// if (array[i].indexOf(num) != -1) {
// return console.log('有');
// }
// }
// 解法二.嵌套循環(huán)
// for(let i=0;i<array.length;i++){
// for(let j=0;j<array[i].length;j++){
// if(array[i][j]==num){
// return '有'
// }
// }
// }
// 解法三.數(shù)組扁平化,然后indexOf查找
let newArray = toStr(array)
console.log(newArray)
if (newArray.indexOf(num) != -1) {
return console.log('有');
}
return console.log('沒有');
}
// 數(shù)組扁平化
function toStr(arr) {
return arr.toString().split(',').map(item => {
return Number(item)
})
}
let ary = [[1, 2, 3, 4], [2, 3, 4, 5]]
sortList(ary, 5)
題目二: 替換空格: 請實現(xiàn)一個函數(shù),將一個字符串中的空格替換成“%20”。例如,當(dāng)字符串為 We Are Happy.則經(jīng)過替換之后的字符串為 We%20Are%20Happy
function replaceSpace(str) {
// 解法一:暴力for循環(huán)對比
// let newStr=''
// for(let i=0;i<str.length;i++){
// if(str[i]==' '){
// newStr+='%20'
// }else{
// newStr+=str[i]
// }
// }
// console.log(newStr)
// return newStr
// 解法二:split分割成數(shù)組,再進行join轉(zhuǎn)字符串
// let newStr = str.split分割成數(shù)組,再進行join轉(zhuǎn)字符串(" ").join("%20");
// console.log(newStr)
// return newStr
// 解法三:正則
// var reg = / /g;
// let newStr=str.replace(reg, "%20");
// console.log(newStr)
// return newStr
}
replaceSpace('We Are Happy')
題目三:從尾到頭打印鏈表: 輸入一個鏈表,從尾到頭打印鏈表每個節(jié)點的值。
思路,利用棧的特性先進后出,模擬壓棧,然后再進行出棧實現(xiàn)
class Node {
constructor(data) {
this.data = data
this.next = null
}
}
function printNode(node) {
console.log(node)
// 壓棧實現(xiàn)
let stock = new Array()
let NodeNextElm = node
while (NodeNextElm !== null) {
// console.log(stock)
stock.push(NodeNextElm.data)
NodeNextElm = NodeNextElm.next
}
while (stock.length > 0) {
console.log(stock.pop())
}
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
node1.next = node2
node2.next = node3
printNode(node1)
題目四:重建二叉樹: 輸入某二叉樹的前序遍歷和中序遍歷的結(jié)果,請重建出該二叉樹。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。例如輸入前序遍歷序列 {1,2,4,7,3,5,6,8}和中序遍歷序列 {4,7,2,1,5,3,8,6},則重建二叉樹并返回。
一.
①[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]-> val=>1 ->L([2,4,7],[4,7,2]) & R([3,5,6,8],[5,3,8,6]) 根節(jié)點 1 ,有左右節(jié)點
二.
①L([2,4,7],[4,7,2])-> val=>2 ->L([4,7],[4,7]) && R(null , null) 根節(jié)點2(屬1的左節(jié)點) ,有左節(jié)點,無右節(jié)點
②R([3,5,6,8],[5,3,8,6])-> val=>3 ->L([5],[5]) && R([6,8],[6,8]) 根節(jié)點3(屬1的右節(jié)點) ,有左右節(jié)點
三.
①L([4,7],[4,7]) ->val=>4 -> L(null , null) && R([7],[7]) 根節(jié)點4(屬2的左節(jié)點) ,有右節(jié)點,無左節(jié)點
②R([6,8],[8,6]) -> val=>6 -> L([8] , [8]) && R(null , null) 根節(jié)點6(屬3的右節(jié)點),有左節(jié)點,無右節(jié)點
③L([5],[5]) -> val=>5->(null,null)->終止 尾節(jié)點5(屬3的左節(jié)點)
四.
①R([7],[7]) -> val=>7 ->終止 尾節(jié)點7(屬4的右節(jié)點)
②L([8],[8]) -> val=>8 ->終止 尾節(jié)點8(屬6的左節(jié)點)
function rebuildBinaryTree(front, centre) {
if (!front || front.length == 0) {
return null;
}
var TreeNode = {
val: front[0]
};
for (var i = 0; i < front.length; i++) {
//找到中序遍歷根節(jié)點位置
if (centre[i] === front[0]) {
//對于中序遍歷,根節(jié)點左邊的節(jié)點位于二叉樹的左邊,根節(jié)點右邊的節(jié)點位于二叉樹的右邊
TreeNode.left = rebuildBinaryTree(front.slice(1, i + 1), centre.slice(0, i));
TreeNode.right = rebuildBinaryTree(front.slice(i + 1), centre.slice(i + 1));
}
}
return TreeNode;
}
let tree = rebuildBinaryTree([1, 2, 4, 7, 3, 5, 6, 8], [4, 7, 2, 1, 5, 3, 8, 6])
console.log(tree)
題目五:用兩個棧實現(xiàn)隊列: 用兩個棧來實現(xiàn)一個隊列,完成隊列的 Push 和 Pop 操作。
思路:使用兩個數(shù)組模擬棧,一個用于push一個用于pop
let stack_push = []
let stack_pop = []
function pushData(data) {
stack_push.push(data)
}
function popData() {
if (stack_pop.length > 0) {
console.log(stack_pop.pop())
} else {
if (stack_push.length > 0) {
while (stack_push.length > 0) {
stack_pop.push(stack_push.pop())
}
console.log(stack_pop.pop());
} else {
console.log('隊列為空');
}
}
}
pushData(1)
pushData(2)
pushData(3)
pushData(4)
console.log(stack_push);
console.log(stack_pop);
popData()
console.log(stack_push);
console.log(stack_pop);
pushData(5)
console.log(stack_push);
console.log(stack_pop);
popData()
popData()
popData()
popData()
popData()
console.log(stack_push);
console.log(stack_pop);
題目六:旋轉(zhuǎn)數(shù)組的最小數(shù)字: 把一個數(shù)組最開始的若干個元素搬到數(shù)組的末尾,我們稱之為數(shù)組的旋轉(zhuǎn)。 輸入一個非遞減排序的數(shù)組的一個旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素。例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉(zhuǎn),該數(shù)組的最小值為 1。NOTE:給出的所有元素都大于 0,若數(shù)組大小為 0,請返回 0。
function revoleArray(array) {
let min = array[0];
let index = 0;
for (let i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i]
index = i
}
}
let newArray = array.slice(0, index)
let newArray2 = array.slice(index)
return newArray2.concat(newArray)
}
let newArray = revoleArray([3, 4, 5, 1, 2])
console.log(newArray)
題目七:斐波那契數(shù)列: 大家都知道斐波那契數(shù)列,現(xiàn)在要求輸入一個整數(shù) n,請你輸出斐波那契數(shù)列的第 n 項,n<=39。
思路:斐波那契數(shù)列:[1,1,2,3,5,8,13,...] 每個數(shù)等于前兩個數(shù)之和
//解法一:遞歸
function fbnq(n) {
if (n <= 1) {
return 1
}
return fbnq(n - 1) + fbnq(n - 2)
}
// 解法二:循環(huán)
function Fibonacci(n) {
if (n <= 1) {
return 1;
} else {
let before_one=0,before_two=0,result=0,List=[]
for(let i=0;i<=n;i++){
before_one=List[i-1]>=0?List[i-1]:0
before_two=List[i-2]>=0?List[i-2]:0
result=before_one + before_two
if(result<=1)result=1
List.push(result)
}
return List[n]
}
}
let a = fbnq(5)
console.log(a);
let b = Fibonacci(5)
console.log(b);
題目八:跳臺階: 一只青蛙一次可以跳上 1 級臺階,也可以跳上 2 級。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。
思路:jump(1)=1 jump(2)=2 jump(3)=3 jump(4)=5 jump(5)=8 類似于斐波那契數(shù)列只不過就是前兩項變?yōu)?,2
function jump(n){
if(n<=2){
return n;
}
return jump(n-1) + jump(n-2)
}
let jumpNum=jump(5)
console.log(jumpNum);
題目九:變態(tài)跳臺階: 一只青蛙一次可以跳上 1 級臺階,也可以跳上 2 級……它也可以跳上 n 級。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。
思路:jump(1)=1 jump(2)=2 jump(3)=4 jump(4)=8 2的n次方
function btJump(n){
// 解法一:用位運算符 2的n次方最簡單就是用位運算符 1<<n(將1左移n位數(shù)) 1:0001 2:0010 4:0100 8:1000
// return 1<<(--n);
// 解法二:遞歸
if(n<=1){
return n
}else{
return 2*btJump(n-1)
}
}
let jumpNum=btJump(5)
console.log(jumpNum);
題目十:矩形覆蓋: 我們可以用 21 的小矩形橫著或者豎著去覆蓋更大的矩形。請問用 n 個 21 的小矩形無重疊地覆蓋一個 2*n 的大矩形,總共有多少種方法?
function rectCover(number) {
if (number <= 2) {
return number;
} else {
return rectCover(number - 1) + rectCover(number - 2);
}
}
let rectNum=rectCover(4)
console.log(rectNum);
題目十一:二進制中 1 的個數(shù): 輸入一個整數(shù),輸出該數(shù)二進制表示中 1 的個數(shù)。其中負(fù)數(shù)用補碼表示。
思路:一、使用split('')將其轉(zhuǎn)換為字符數(shù)組然后reduce進行累加 二、暴力for循環(huán)判斷
function countOneNum(num) {
let count=0;
// toString(2)轉(zhuǎn)化為二進制
// 解法一:使用split('')將其轉(zhuǎn)換為字符數(shù)組然后reduce進行累加
count = num.toString(2).split('').reduce((acc, cur) => {
console.log(acc, cur)
return acc + parseInt(cur)
}, 0);
let Binary=num.toString(2)
// 解法二:for循環(huán)
for(let i=0;i<Binary.length;i++){
if(Binary[i]==1)count++
}
return count
}
let count = countOneNum(5)
console.log(count);
題目十二:數(shù)值的整數(shù)次方: 給定一個 double 類型的浮點數(shù) base 和 int 類型的整數(shù) exponent。求 base 的 exponent 次方。
function md(base,exponent){
if(exponent<0){
if(base<0){
return '我也不知道怎么變負(fù)數(shù)'
}else{
return 1/md(base,-exponent)
}
}else if(exponent==0){
return 1
}else{
return base*md(base,exponent-1)
}
}
let total=md(2.33,-5)
console.log(total);
題目十三:調(diào)整數(shù)組順序使奇數(shù)位于偶數(shù)前面: 輸入一個整數(shù)數(shù)組,實現(xiàn)一個函數(shù)來調(diào)整該數(shù)組中數(shù)字的順序,使得所有的奇數(shù)位于數(shù)組的前半部分,所有的偶數(shù)位于位于數(shù)組的后半部分,并保證奇數(shù)和奇數(shù),偶數(shù)和偶數(shù)之間的相對位置不變。
思路:循環(huán)找出奇偶列表,然后concat合并
function changeArray(array) {
let jList = [], oList = []
array.forEach(item => {
if (item % 2 == 0) {
oList.push(item)
} else {
jList.push(item)
}
});
return jList.concat(oList)
}
let NewArray = changeArray([2, 3, 4, 5, 9, 8, 7])
console.log(NewArray);
題目十四:鏈表中倒數(shù)第 k 個節(jié)點: 輸入一個鏈表,輸出該鏈表中倒數(shù)第 k 個結(jié)點。
思路:模擬棧將鏈表push進棧,隨后判斷k是否大于等于鏈表的長度,反轉(zhuǎn)數(shù)組再取出下標(biāo)為k-1的節(jié)點
class Node{
constructor(data){
this.data=data
this.next=null
}
}
function getIndexNode(node,index){
let stack=[]
let nextNodeElm=node
while(nextNodeElm!=null){
stack.push(nextNodeElm.data)
nextNodeElm=nextNodeElm.next
}
if(stack.length<index){
return '輸入的節(jié)點請小于等于鏈表長度'
}
stack.reverse()
return stack[index-1]
}
const node1=new Node(1)
const node2=new Node(2)
const node3=new Node(3)
const node4=new Node(4)
const node5=new Node(5)
node1.next=node2
node2.next=node3
node3.next=node4
node4.next=node5
let node=getIndexNode(node1,5)
console.log(node)
題目十五:反轉(zhuǎn)鏈表: 輸入一個鏈表,反轉(zhuǎn)鏈表后,輸出鏈表的所有元素。
class Node {
constructor(data) {
this.data = data
this.next = null
}
}
function revolveNode(node) {
if (node == null) {
return false;
}
let p1 = node, p2 = null, temp = null;
while (p1) {
temp = p1.next;
p1.next = p2;
p2 = p1;
p1 = temp;
}
return p2;
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
const node4 = new Node(4)
const node5 = new Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
let node = revolveNode(node1)
console.log(node)
題目十六:合并兩個排序的鏈表: 輸入兩個單調(diào)遞增的鏈表,輸出兩個鏈表合成后的鏈表,當(dāng)然我們需要合成后的鏈表滿足單調(diào)不減規(guī)則。
class Node {
constructor(data) {
this.data = data
this.next = null
}
}
function Merge(node1, node2) {
console.log(node1, node2);
if (node1 == null) {
return node2;
} else if (node2 == null) {
return node1;
}
var result = {};
if (node1.data < node2.data) {
result = node1;
result.next = Merge(node1.next, node2);
} else {
result = node2;
result.next = Merge(node1, node2.next);
}
return result;
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
const node4 = new Node(4)
const node5 = new Node(5)
const node6 = new Node(6)
const node7 = new Node(7)
const node8 = new Node(8)
const node9 = new Node(9)
const node10 = new Node(10)
node1.next = node2
node2.next = node3
node3.next = node5
node4.next = node6
node5.next = node7
node6.next = node8
node8.next = node9
node9.next = node10
let newNode=Merge(node1,node4)
console.log(newNode);
題目十七:順時針打印矩陣: 輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數(shù)字
例如,如果輸入如下矩陣:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
則依次打印出數(shù)字 1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10
思路:依次順序打印出第一行,然后逆時針旋轉(zhuǎn)矩陣,繼續(xù)打印第一行,直到完成
function rotateMatrix90Clockwise(matrix) {
const numRows = matrix.length;
const numCols = matrix[0].length;
let rotatedMatrix = new Array(numCols).fill(0).map(() => new Array(numRows));
for (let i = 0; i < numRows; i++) {
for (let j = 0; j < numCols; j++) {
rotatedMatrix[numCols - j - 1][i] = matrix[i][j];
}
}
return rotatedMatrix;
}
function printNum(array){
let list=array.slice(0,1)[0]
// console.log(list);
let newList=list.reverse()
while(newList.length>0){
console.log(newList.pop())
}
// console.log(newList);
array=array.slice(1,)
if(array.length==0){
return
}
let newArray=rotateMatrix90Clockwise(array)
printNum(newArray)
}
const originalMatrix = [
[1, 2, 3,4],
[5, 6,7,8],
[9,10,11,12],
[13,14,15,16]
];
printNum(originalMatrix);
題目十八:定義一個棧,實現(xiàn) min 函數(shù):定義棧的數(shù)據(jù)結(jié)構(gòu),請在該類型中實現(xiàn)一個能夠得到棧最小元素的 min 函數(shù)。
let stack_push = []
let stack_pop = []
function pushData(data) {
stack_push.push(data)
}
function popData() {
if (stack_pop.length > 0) {
console.log(stack_pop.pop());
} else {
if (stack_push.length > 0) {
while (stack_push.length > 0) {
stack_pop.push(stack_push.pop())
}
console.log(stack_pop.pop());
} else {
console.log('空棧')
}
}
}
function searchMin() {
while (stack_pop.length > 0) {
stack_push.push(stack_pop())
}
let min = stack_push[0]
for (let index = 0; index < stack_push.length; index++) {
if (stack_push[index] < min) {
min = stack_push[index]
}
}
return min
}
pushData(1)
pushData(2)
pushData(3)
pushData(0)
pushData(4)
let min = searchMin()
console.log(min);
題目十九:棧的壓入彈出:輸入兩個整數(shù)序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為該棧的彈出順序。假設(shè)壓入棧的所有數(shù)字均不相等。
例如:序列 1,2,3,4,5 是某棧的壓入順序,序列 4,5,3,2,1 是該壓棧序列對應(yīng)的一個彈出序列,但 4,3,5,1,2 就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)
思路:一、模擬壓棧彈棧 二、直接反轉(zhuǎn)數(shù)組進行pop比較
let stack_push = []
let stack_pop = []
function pushData(data) {
stack_push.push(data)
}
function popData() {
if (stack_pop.length > 0) {
console.log(stack_pop.pop());
} else {
if (stack_push.length > 0) {
while (stack_push.length > 0) {
stack_pop.push(stack_push.pop())
}
console.log(stack_pop.pop());
} else {
console.log('空棧')
}
}
}
function testStack(pushStack,popStack){
// 解法一:模擬壓棧彈棧
// if(pushStack.length != popStack.length){
// return '不是'
// }
// let NewPushStack=pushStack.reverse()
// let NewPopStack=popStack.reverse()
// while(NewPushStack.length>0){
// pushData(NewPushStack.pop())
// }
// while(stack_push.length>0){
// if(stack_push.pop() != NewPopStack.pop())return '不對'
// }
// return '正確'
// 解法二:直接反轉(zhuǎn)數(shù)組進行pop比較
if(pushStack.length != popStack.length){
return '不是'
}
let NewPopStack=popStack.reverse()
while(pushStack.length>0){
if(pushStack.pop() != NewPopStack.pop())return '不對'
}
return '正確'
}
let result=testStack([1,2,3,4,5],[5,4,3,2,1])
console.log(result);
題目二十:復(fù)雜鏈表的復(fù)制:輸入一個復(fù)雜鏈表(每個節(jié)點中有節(jié)點值,以及兩個指針,一個指向下一個節(jié)點,另一個特殊指針指向任意一個節(jié)點),返回結(jié)果為復(fù)制后復(fù)雜鏈表的 head。(注意,輸出結(jié)果中請不要返回參數(shù)中的節(jié)點引用,否則判題程序會直接返回空)
function copyNode(pHead){
console.log(pHead)
if (!pHead) {
return null;
}
// 復(fù)制頭結(jié)點
var node = new Node(pHead.data);
node.other = pHead.other;
// 遞歸其他節(jié)點
node.next = copyNode(pHead.next);
return node;
}
class Node {
constructor(data) {
this.data = data
this.next = null
this.other = null
}
}
const node1 = new Node(1)
const node2 = new Node(2)
const node3 = new Node(3)
node1.next = node2
node2.next = node3
node1.other = node2
node2.other = node3
node3.other = node1
let newNode=copyNode(node1)
console.log(newNode);
題目二十一:字符串的排列:輸入一個字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串 abc,則打印出由字符 a,b,c 所能排列出來的所有字符串 abc,acb,bac,bca,cab 和 cba。輸入描述:輸入一個字符串,長度不超過 9(可能有字符重復(fù)),字符只包括大小寫字母。
function permute(str, left = 0, right = str.length - 1) { //abc left 2
console.log(left,right)
// 如果左邊界等于右邊界,說明只剩下一個字符,打印它
if (left === right) {
console.log("結(jié)果:",str);
} else {
// 遍歷從l到r的每個位置
for (let i = left; i <= right; i++) {
// 將當(dāng)前位置i的字符與左邊界l的字符交換
str = swap(str, left, i);
console.log("str:",str,"left:",left,"I:",i);
// 遞歸地對剩余的子字符串進行排列(注意left+1表示排除已固定的字符)
permute(str, left + 1, right);
// 遞歸返回后,需要將字符交換回原來的位置,以便下一次循環(huán)使用原始字符串
str = swap(str, left, i);
}
}
}
function swap(str, i, j) {
// 將字符串轉(zhuǎn)換為字符數(shù)組
let arr = str.split('');
// 解構(gòu)交換元素
[arr[i], arr[j]] = [arr[j], arr[i]];
// 將修改后的數(shù)組轉(zhuǎn)換回字符串
return arr.join('');
}
permute('abc');
題目二十二:數(shù)組中出現(xiàn)次數(shù)超過一半的數(shù)字: 數(shù)組中有一個數(shù)字出現(xiàn)的次數(shù)超過數(shù)組長度的一半。請找出這個數(shù)字。例如輸入一個長度為 9 的數(shù)組{1,2,3,2,2,2,5,4,2}。由于數(shù)字 2 在數(shù)組中出現(xiàn)了 5 次,超過數(shù)組長度的一半,因此輸出 2。如果不存在則輸出 0。
function moreAHalfNum(array){
let length=array.length
let maxLength=Math.floor(length/2)
let computedTotal={}
let maxNum=null
array.forEach(item => {
if(computedTotal[item]){
computedTotal[item]++
if(computedTotal[item]>maxLength)maxNum=item
}else{
computedTotal[item]=1
}
});
return maxNum?maxNum:0
}
let num=moreAHalfNum([1,2,3,4,6,6,6,6,6])
console.log(num);
題目二十三:最小的 K 個數(shù):輸入 n 個整數(shù),找出其中最小的 K 個數(shù)。例如輸入 4,5,1,6,2,7,3,8 這 8 個數(shù)字,則最小的 4 個數(shù)字是 1,2,3,4 。
思路:先sort排序,此時數(shù)組是從小到大排序,取前k個即可
function searchMinCountNum(array,K){
let NewArray=array.sort()
return NewArray.slice(0,K)
}
let countNum=searchMinCountNum([2,1,8,9,6,5],3)
console.log(countNum);
題目二十四:把數(shù)組排成最小的數(shù):輸入一個正整數(shù)數(shù)組,把數(shù)組里所有數(shù)字拼接起來排成一個數(shù),打印能拼接出的所有數(shù)字中最小的一個。例如輸入數(shù)組{3,32,321},則打印出這三個數(shù)字能排成的最小數(shù)字為 321323。
function PrintMinNumber(numbers) {
numbers.sort(function (a, b) {
var s1 = a + '' + b;
var s2 = b + '' + a;
for (var i = 0; i < s1.length; i++) {
if (s1.charAt(i) > s2.charAt(i)) {
return 1
} else if (s1.charAt(i) < s2.charAt(i)) {
return -1;
}
}
return 1
})
console.log(numbers);
var result = "";
numbers.map(function (num) {
result = result.concat(num)
})
return result;
}
let num=PrintMinNumber([32,3,321])
console.log(num);
題目二十五:丑數(shù)(待深入理解):把只包含質(zhì)因子 2、3 和 5 的數(shù)稱作丑數(shù)。例如 6、8 都是丑數(shù),但 14 不是,因為它包含因子 7。 習(xí)慣上我們把 1 當(dāng)做是第一個丑數(shù)。求按從小到大的順序的第 N 個丑數(shù)。
function getUglyNumberSolution(index) {
if (index == 0) return 0
var uglys = [1];
var factor2 = 0, factor3 = 0, factor5 = 0;
for (var i = 1; i < index; i++) {
uglys[i] = Math.min(uglys[factor2] * 2, uglys[factor3] * 3, uglys[factor5] * 5)
if (uglys[i] == uglys[factor2] * 2) factor2++;
if (uglys[i] == uglys[factor3] * 3) factor3++;
if (uglys[i] == uglys[factor5] * 5) factor5++;
}
console.log(uglys);
return uglys[index - 1]
}
let count=getUglyNumberSolution(11)
console.log(count);
題目二十六:第一個只出現(xiàn)一次的字符:在一個字符串(1<=字符串長度<=10000,全部由大寫字母組成)中找到第一個只出現(xiàn)一次的字符,并返回它的位置。
function getFirstChar(str){
str=str.toUpperCase()
let chat={}
for (let i = 0; i < str.length; i++) {
if(chat[str[i]]){
chat[str[i]]++
}else{
chat[str[i]]=1
}
}
console.log(chat);
for (let i = 0; i <= str.length; i++) {
if(chat[str[i]]==1){
return str.indexOf(str[i]) +"=>"+str[i]
}
}
return '無只出現(xiàn)一次的字符'
}
let index=getFirstChar('hheello')
console.log(index);
題目二十七:數(shù)組中的逆序?qū)Γ涸跀?shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序?qū)Α]斎胍粋€數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù) P。
function getReverseNum(array){
let count=0
let towNum=[]
if(array.length>1){
towNum=array.slice(0,2)
console.log(towNum);
if(towNum[0]>towNum[1]){
count++
}
return count + getReverseNum(array.slice(2,))
}
return count
}
let num=getReverseNum([2,1,3,4,5,4,5,4,5,4,5,4])
console.log(num);
題目二十八:數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù):統(tǒng)計一個數(shù)字:在排序數(shù)組中出現(xiàn)的次數(shù)。例如輸入排序數(shù)組{ 1, 2, 3, 3, 3, 3, 4, 5}和數(shù)字 3 ,由于 3 在這個數(shù)組中出現(xiàn)了 4 次,因此輸出 4 。
function getNumFindCount(array,num){
let count=0
array.forEach(item => {
if(item==num)count++
});
return count
}
let count=getNumFindCount([1,2,3,3,3,4,5],3)
console.log(count);
題目二十九:數(shù)組中只出現(xiàn)一次的數(shù)字:一個整型數(shù)組里除了兩個數(shù)字之外,其他的數(shù)字都出現(xiàn)了兩次。請寫程序找出這兩個只出現(xiàn)一次的數(shù)字。
function getOnlyOneNum(array) {
// 因為new Set去重后返回的是一個對象Set([1,2,...]),所以要用Array.from轉(zhuǎn)換為數(shù)組
let numList = Array.from(new Set(array))
let onlyOneList = []
numList.forEach(item => {
let count = 0
array.forEach(item2 => {
if (item2 == item) count++
})
if (count == 1) onlyOneList.push(item)
})
console.log(onlyOneList);
}
getOnlyOneNum([1, 2, 2, 3, 3, 4])
題目三十:和為 S 的連續(xù)正數(shù)序列:小明很喜歡數(shù)學(xué),有一天他在做數(shù)學(xué)作業(yè)時,要求計算出 9~16 的和,他馬上就寫出了正確答案是 100。但是他并不滿足于此,他在想究竟有多少種連續(xù)的正數(shù)序列的和為 100(至少包括兩個數(shù))。沒多久,他就得到另一組連續(xù)正數(shù)和為 100 的序列:18,19,20,21,22。現(xiàn)在把問題交給你,你能不能也很快的找出所有和為 S 的連續(xù)正數(shù)序列?Good Luck!輸出描述:輸出所有和為 S 的連續(xù)正數(shù)序列。序列內(nèi)按照從小至大的順序,序列間按照開始數(shù)字從小到大的順序。
function getTotalNum(sum) {
if (sum < 2) return [];
var result = [];
var a = 0, b = 0, total = 0;
while (a <= Math.floor(sum / 2)) {
if (total < sum) {
b++;
total += b;
} else if (total > sum) {
total -= a
a++;
} else {
var temp = [];
for (var i = a; i <= b; i++) {
temp.push(i)
}
result.push(temp)
if (a + 1 < b) {
total -= a;
a++
} else {
break;
}
}
}
return result;
}
let list=getTotalNum(100)
console.log(list);
題目三十一:和為 S 的兩個數(shù)字:輸入一個遞增排序的數(shù)組和一個數(shù)字 S,在數(shù)組中查找兩個數(shù),是的他們的和正好是 S,如果有多對數(shù)字的和等于 S,輸出兩個數(shù)的乘積最小的。輸出描述:對應(yīng)每個測試案例,輸出兩個數(shù),小的先輸出。
function totaleqNum(array, sum) {
let list = []
for (let i = 0; i < array.length; i++) {
for (let j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == sum) {
let data = {
list: [array[i], array[j]],
result: array[i] * array[j]
}
list.push(data)
}
}
}
if (list.length > 1) {
let min = list[0].result
list.forEach(item => {
if (item.result < min) {
return item.list
}
})
return list[0].list
}
return list[0].list
}
let result=totaleqNum([1, 2, 3, 4, 5, 6], 5)
console.log(result);
題目三十二:左旋轉(zhuǎn)字符串:匯編語言中有一種移位指令叫做循環(huán)左移(ROL),現(xiàn)在有個簡單的任務(wù),就是用字符串模擬這個指令的運算結(jié)果。對于一個給定的字符序列 S,請你把其循環(huán)左移 K 位后的序列輸出。例如,字符序列 S=”abcXYZdef”,要求輸出循環(huán)左移 3 位后的結(jié)果,即 “XYZdefabc”。
function transformStr(str,left){
if(left>str.length){
return '位移長度不能超過字符長度'
}
let leftStr=str.slice(left,)
let rightStr=str.slice(0,left)
return leftStr+rightStr
}
let newStr=transformStr('hello',2)
console.log(newStr);
題目三十三:翻轉(zhuǎn)單詞順序列:牛客最近來了一個新員工 Fish,每天早晨總是會拿著一本英文雜志,寫些句子在本子上。同事 Cat 對 Fish 寫的內(nèi)容頗感興趣,有一天他向 Fish 借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。后來才意識到,這家伙原來把句子單詞的順序翻轉(zhuǎn)了 ,正確的句子應(yīng)該是“I am a student.”。Cat 對一一的翻轉(zhuǎn)這些單詞順序可不在行,你能幫助他么?
思路:split對字符串按照空格分隔成數(shù)組,然后reverse反轉(zhuǎn)數(shù)組,最后join合并成字符串
function revolveStr(str){
return newStrList=str.split(" ").reverse().join(" ")
}
let newStr=revolveStr("I am a student.")
console.log(newStr);
題目三十四:1+2+3+...+n:求 1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case 等關(guān)鍵字及條件判斷語句(A?B:C)。
function totalNum(n){
var sum=n;
var a=(n>0)&&((sum+=totalNum(n-1))>0)
return sum
}
let total=totalNum(3)
console.log(total);
題目三十五:把字符串轉(zhuǎn)換成整數(shù)。:將一個字符串轉(zhuǎn)換成一個整數(shù),要求不能使用字符串轉(zhuǎn)換整數(shù)的庫函數(shù)。數(shù)值為 0 或者字符串不是一個合法的數(shù)值則返回 0。輸入描述:輸入一個字符串,包括數(shù)字字母符號,可以為空。輸出描述:如果是合法的數(shù)值表達(dá)則返回該數(shù)字,否則返回 0。
思路:循環(huán)字符串,判斷每個字符是否為數(shù)字,因為不能使用字符串轉(zhuǎn)換整數(shù)的庫函數(shù),所以要定義一個函數(shù)判斷字符串是否在0~9之間,是即為數(shù)字。
function strToNumber(str){
let newStr=''
for (let i = 0; i < str.length; i++) {
if(isNumber(str[i])){
newStr+=str[i]
}
}
return newStr
}
function isNumber(data){
if(data>=0 || data<=9){
return true
}
return false
}
let newStr=strToNumber('+2147#48^3647')
console.log(newStr);
題目三十六:數(shù)組中重復(fù)的數(shù)字:在一個長度為 n 的數(shù)組里的所有數(shù)字都在 0 到 n-1 的范圍內(nèi)。數(shù)組中某些數(shù)字是重復(fù)的,但不知道有幾個數(shù)字重復(fù)了,也不知道每個數(shù)字重復(fù)了幾次。請找出數(shù)組中任意一個重復(fù)的數(shù)字。
思路,使用set對數(shù)組進行去重,然后對數(shù)組進行遍歷,再去遍歷原數(shù)組,找出數(shù)組里第一個出現(xiàn)重復(fù)數(shù)字,隨機try catch拋出異常進行中斷遍歷并進行返回
function searchFirstFindTwoNum(array) {
try {
Array.from(new Set(array)).forEach(item => {
let count = 0
array.forEach(item2 => {
if (item == item2) count++
if (count > 1) throw new Error(item)
})
})
} catch (e) {
return e.message
}
return '數(shù)組內(nèi)無重復(fù)數(shù)字'
}
let number = searchFirstFindTwoNum([1, 2, 3, 3, 4, 5])
console.log(number);
題目三十七:構(gòu)建乘積數(shù)組:給定一個數(shù)組 A[0,1,...,n-1],請構(gòu)建一個數(shù)組 B[0,1,...,n-1],其中 B 中的元素 B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法。
function getTotalList(array) {
let newArray = []
for (let i = 0; i < array.length; i++) {
newArray[i] = getTotal(array) * array[i-1]-array[i+1]
console.log(newArray[i]);
}
return newArray
}
function getTotal(array) {
let total = 1;
array.forEach(item => total *= item);
return total
}
let newArray = getTotalList([2, 4, 6, 7, 8])
console.log(newArray);
題目三十八:字符流中第一個不重復(fù)的字符:請實現(xiàn)一個函數(shù)用來找出字符流中第一個只出現(xiàn)一次的字符。例如,當(dāng)從字符流中只讀出前兩個字符 "go" 時,第一個只出現(xiàn)一次的字符是 "g" 。當(dāng)從該字符流中讀出前六個字符 "google" 時,第一個只出現(xiàn)一次的字符是 "l"。 輸出描述:如果當(dāng)前字符流沒有存在出現(xiàn)一次的字符,返回#字符。
思路:先對原數(shù)組進行去重獲取字符列表,隨后單個出現(xiàn)單詞給個默認(rèn)值為首個字符,方便后續(xù)判斷,首先遍歷去重后的字符數(shù)組,根據(jù)每個字符對原字符串進行遍歷查詢是否重復(fù),如果出現(xiàn)重復(fù)且重復(fù)詞與單個出現(xiàn)字符不一致,則證明出現(xiàn)首個單一字符,則拋出異常結(jié)束遍歷并返回,當(dāng)重復(fù)時單個出現(xiàn)字符為當(dāng)前字符,如果是則表示前面并無單一字符,并判斷當(dāng)前位置是否已經(jīng)遍歷到最末端了,如果不是繼續(xù)下一個字符的遍歷,如果當(dāng)前位置為字符串倒數(shù)第二的位置,則下一個字符必定為單一出現(xiàn)單詞,則直接返回。
function searchFirstFindOneStr(str) {
try {
let array = Array.from(new Set(str.split("")))
let keyword = array[0]
array.forEach(item => {
let count = 0
for (let i = 0; i < str.length; i++) {
if (item == str[i]) count++
if (count > 1 && keyword != str[i]) throw new Error(keyword)
if (count > 1 && keyword == str[i]) {
count = 0
if (i < str.length-1 && i < str.length - 2) keyword = str[i + 1]
if (i == str.length - 2) throw new Error(str[str.length - 1])
}
}
})
} catch (e) {
return e.message
}
return '#'
}
let str = searchFirstFindOneStr("hheello66")
console.log(str);
題目三十九:數(shù)據(jù)流中的中位數(shù)(待深入理解):如何得到一個數(shù)據(jù)流中的中位數(shù)?如果從數(shù)據(jù)流中讀出奇數(shù)個數(shù)值,那么中位數(shù)就是所有值排序之后位于中間的數(shù)值。如果數(shù)據(jù)流中讀出偶數(shù)個數(shù)值,那么中位數(shù)就是所有數(shù)值排序之后中間兩個數(shù)的平均值。
function getCenterNum(array){ //[1,2,3,4,5]
let index=Math.floor(array.length/2)
let newArray=array.sort()
if(newArray.length%2==0){
return (newArray[index-1]+newArray[index])/2
}else{
return newArray[index]
}
}
let num=getCenterNum([3,2,3,7,5,6])
console.log(num);
題目四十:滑動窗口中的最大值(待深入理解):給定一個數(shù)組和滑動窗口的大小,找出所有滑動窗口里數(shù)值的最大值。例如,如果輸入數(shù)組{2,3,4,2,6,2,5,1}及滑動窗口的大小 3,那么一共存在 6 個滑動窗口,他們的最大值分別為{4,4,6,6,6,5};
思路:針對數(shù)組{2,3,4,2,6,2,5,1}的滑動窗口有以下 6 個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
最大值分別就是每個窗口[2,3,4],[3,4,2],[4,2,6],[2,6,2],[6,2,5],[2,5,1]中元素最大的一個,即為[4,4,6,6,6,5]
function slideWindowMax(array,size){
let allWindows=[],allMax=[]
while(array.length>=size){
allWindows.push(array.slice(0,size))
array=array.slice(1,)
}
allWindows.forEach(i => {
let max=i[0]
i.forEach(j=>{
if(j>max)max=j
})
allMax.push(max)
});
return allMax
}
let maxList=slideWindowMax([2,3,4,2,6,2,5,1],3)
console.log(maxList);
上述為個人學(xué)習(xí)整理內(nèi)容,水平有限,如有錯誤之處,望各位園友不吝賜教!如果覺得不錯,請點個贊和關(guān)注支持一下!謝謝~??????? \???

浙公網(wǎng)安備 33010602011771號