1. 程式人生 > >前端面試演算法集合

前端面試演算法集合

問題1:給定一個數組a和一個長度值l,生成一個指定長度值為l的新陣列b,要求b中的每一個元素都是從a中隨機獲取的,且陣列元素不可重複。

function generate(a,l){
if(a.length < l) return '老陣列長度不足!';
/*a長度可能超出,可以生成新陣列後擷取長度為l的賦值給b,也可以生成為l的b(這裡選第二種)*/
var i=0, tmp=[], b=[];
// 每次獲取a的一個隨機元素,同時將
while(i<l && tmp.length<=a.length) {
var random = Math.floor(Math.random()*(a.length));
if(tmp.indexOf(random) == -1) { // 判斷隨機元素是否已經使用過,未使用則放入臨時陣列記錄
tmp.push(random);
var number = a[random]; // 獲取陣列a中的隨機數
console.log(random+"..."+number);
if(b.indexOf(number) == -1) { //部分IE不支援indexOf請自行解決。也可以使用jquery的$.inArray方法,總之就是不重複扔進b
b.push(number);
i++; // 新隨機數時+1
}
}
}
if(b.length==l) return b;
else return '新陣列長度不足: '+ b;
}

// 測試
var a=[3,2,1,6,3,9,2,5];
generate(a, 5)

問題2:使用js寫一個棧結構。然後如何讓這個棧滿足兩個呼叫者同時使用的要求?

function Stack() {
  this.dataStore = [];
  this.top = 0;//棧頂元素的位置
  this.push = push;
  this.pop = pop;
  this.peek = peek;
  this.length=length;
  this.clear=clear;
}

function push(element) {//進棧
   this.dataStore[this.top++] = element;
}

function pop() {//出棧
  return this.dataStore[--this.top];
}

function peek() {//棧頂元素
  return this.dataStore[this.top-1];
}

function length() {
  return this.top;
}

function clear() {
  this.top = 0;
}

//測試棧的實現
var s= new Stack();
s.push("D");
s.push("R");
s.push("B");
console.log(s.length());
console.log(s.peek());
console.log(s.clear());
console.log(s.length());

問題3:找出陣列中只出現一次的元素

 function num(arr){
        var str=arr.join(''); 
        var res=[];
        for(var i=0;i<str.length;i++){           
            var num=str.split(str[i]).length-1;
            if(num===1){
                res.push(str[i]);
            }
        }

        return res;

     }
     var arr=[1,2,1,4,3,3];
     console.log(num(arr));

問題4:現在對於給定的一個字串s,請計算出字典序最大的s的子序列。

function max(str){
        //字典序從小到大:abcdefg......
        var arr=str.split('');
        var res=[arr[arr.length-1]];//字串最後一個元素肯定符合條件
        for(var i=arr.length-2;i>=0;i--){//從倒數第二個元素開始,找單調遞增的元素
            if(arr[i]>=res[0]){
                res.unshift(arr[i]);//找到符合的直接加入到res中
            }
        }
        return  res.join('');

     }

     var str='abddaa';
     console.log(max(str));

問題6:把一棵二叉樹變成它的映象二叉樹

function Mirror(root){
            if(root==null){//當一開始根節是空的時候,返回false
                return false;
            }
            if(root.left ==null && root.right ==null){//當只有一個根節點時返回false
                return false;

            }
            //第三種情況:當左右子樹不為空的時候,互動左右子樹節點
            var temp=root.left;
            root.left=root.right;
            root.right=temp;
            if(root.left!=null){//遞迴遍歷左子樹
                Mirror(root.left);
            }
            if(root.right!=null){//遞迴遍歷右子樹
                Mirror(root.right);
            }
        }

問題7:順時針列印矩陣

function printMatrix(matrix)
{
    // write code here
        var row1 = 0;
        var row2 = matrix.length-1;
        var col1 = 0;
        var col2 = matrix[0].length-1;
        var rowflag = 1;
        var colflag = 1;
       var list=[];
        while(row2>=row1 && col2>=col1){
            if(rowflag == 1){
                for(var i=col1; i<=col2; i++)
                    list.push(matrix[row1][i]);
                row1++;
            }
            if(colflag == 1){
                for(var i=row1; i<=row2; i++)
                    list.push(matrix[i][col2]);
                col2--;
            }
            if(rowflag == -1){
                for(var i=col2; i>=col1; i--)
                    list.push(matrix[row2][i]);
                row2--;
            }
            if(colflag == -1){
                for(var i=row2; i>=row1; i--)
                    list.push(matrix[i][col1]);
                col1++;
            }
            rowflag = rowflag*(-1);
            colflag = colflag*(-1);
        }
        
        return list;
 
}

問題8:Fibinacc數列

function Fibnacci(n){
            var res=[0,1];
            if(n<2){
                return res[n];
            }
            var fib1=0;
            var fib2=1;
            var fibn=0;
            for(var i=2;i<=n;i++){
                fibn=fib1+fib2;
                fib1=fib2;
                fib2=fibn;
            }
            return fibn;

        }
function jumpFloor(number)
{
    if(number ===0){
        return 0;
    }
    if(number===1){
        return 1;
}
    if(number ===2){
        return 2;
    }
    var one = 1;
    var two = 2;
    var num = 0;
    for(let i=3;i<=number;i++){
        num = one + two;
        one = two;
        two = num;
         
    }
    return num
}

問題9:在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

function Find(target, array) {
//從最右上角開始確定一個點開始比較
  let i = 0;
  let j = array[i].length - 1;//將最右邊的列作為定點
  while (i < array.length && j >= 0) {
    if (array[i][j] < target) {
      i++;
    } else if (array[i][j] > target) {
      j--;
    } else {
      return true;
    }
  }
  return false;
}

問題10:陣列中出現次數超過一半的元素

方法1:

function MoreThanHalfNum_Solution(numbers)
{
    // write code here
    if(numbers==null){
        return null;
    }    
        var string=numbers.join('');
        var len=Math.floor(numbers.length/2);
        for(var i=0;i<numbers.length;i++){
           var num=string.split(numbers[i]).length-1;
           if(num>len){
              return numbers[i];
               break;
           }
        }    
        return 0;
}

方法2:

function MoreThanHalfNum_Solution(numbers)
{
    // write code here
     var len=numbers.length;
    if(len==0)return 0;
    var num=numbers[0];
        count=1;
    for(var i=0;i<len;i++){
        if(num==numbers[i]){
            count++;
        }else{
            count--;
        }
        if(count==0){
            num=numbers[i];
            count=1;
        }
    }
    count=0;
    for(var i=0;i<len;i++){
        if(numbers[i]==num)count++;
    }
    if(count*2>len)return num;
    return 0;
}

問題11:從尾到頭列印連結串列

//藉助兩個陣列arr1和arr2,arr1用來儲存按連結串列順序壓棧,arr2用來儲存arr1出棧的元素序列
function printListFromTailToHead(head)
{
    // write code here
    if(head==null){
        return [];
    }
    var arr1=[];
    var arr2=[];
    var p=head;
    while(p!=null){//首先將元素壓入棧
        arr1.push(p.val);
        p=p.next;
    };
    while(arr1.length>0){//將arr1裡面的元素依次pop到arr2中
        arr2.push(arr1.pop());
    }
    return arr2;    
}

問題12:重建二叉樹

function reConstructBinaryTree(pre, vin)
{
    // write code here
    var root=pre[0];
    if(pre.length==0||vin.length==0){
        return false;
    }
    for(var i=0;i<vin.length-1;i++){
        if(vin[i]===pre[0]){
           //找左子樹的前序序列和中序序列
            var leftPre=[].concat(pre.splice(1,i+1));
            var leftIn=[].concat(vin.splice(0,i));
            //遞迴遍歷左子樹,並將左子樹加到根節點上
            root.left=reConstructBinaryTree(leftPre,leftIn);
            //找右子樹的前序序列和中序序列
            var rightPre=[].concat(pre.splice(pre.length-i,pre.length));
            var rightIn=[].concat(vin.splice(i+1,vin.length));
            //遞迴遍歷右子樹,並將右子樹加到根節點上
            root.right=reConstructBinaryTree(rightPre,rightIn);
        }
    }
   return  root;    
}

問題13:旋轉陣列的最小數字

function minNumberInRotateArray(rotateArray)
{
    // write code here
     if (array == null || array.length == 0) {//當輸入的是0或者是空的時候
            return 0;
        }
        if (array.length == 1 || array[array.length - 1] > array[0]) {
   //當輸入的是一個元素或者是單調遞增的
            return array[0];
        }
         
        var start = 0;
        var end = array.length - 1;
         
        while (start < end) {
            var mid = parseInt((end - start) / 2 + start);
            if (array[mid] == array[end]) {
                end--;
            } else if (array[mid] < array[end]){
                end = mid;
            } else {
                start = mid + 1;
            }
        }
         
        return array[start];
}

問題14:輸入一個連結串列,輸出該連結串列中倒數第k個結點。

方法一:

function FindKthToTail(head, k)
{
    // write code here
    if(head==null){
        return null;
    }
    var res=[];
    var len=0;
    var p=head;
    while(p!=null){
        res.push(p);
        p=p.next;
    }
    return res[res.length-k];    
}

方法二:

function FindKthToTail(head, k) {
    // write code here 
    if( head==null|| k==0 ){
        return false; 
    } 
    var p1=head;
    var p2=null;
    for( var i=0;i<k-1;i++){ 
        if(p1.next!=null){ 
            p1=p1.next; 
        }else{
            return null;
        } 
    
    } 
    p2=head; 
    while( p1.next!=null){
        p1=p1.next;
        p2=p2.next;
    }
    return p2;
}

問題15:反轉連結串列

/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function ReverseList(pHead)
{
    // write code here
    if(pHead==null){
        return null;
    }
    var arr=[];
    var p1=pHead;
    
    while(p1!=null){
        arr.push(p1);
        p1=p1.next;       
        //數組裡面裝的是節點型別的元素       
    }
    //console.log(arr.length);
    var p2Head=arr.pop();
    var p2=p2Head;
    var pre=p2Head;//用來重新連線的指標
    
    while(arr.length>0){
        p2=arr.pop();
        pre.next=p2;
        pre=p2;
    }
   pre.next=null;//最後給最後一個元素的next置為空
    return p2Head; 
}
module.exports = {
    ReverseList : ReverseList
};

問題16:合併兩個有序連結串列

function ListNode(x){
    this.val = x;
    this.next = null;
}
function Merge(pHead1, pHead2)
{
    // write code here
    var p1=pHead1;
    var p2=pHead2;
    var pHead3=new ListNode(-1);//自己定義一個頭結點
    var p3=pHead3;
    while(p1!=null && p2!=null){        
        if(p1.val<=p2.val){
            p3.next=p1;
            p3=p1;
            p1=p1.next;
            continue;//如果走到最後一個,不能再進行下面的判斷,因為沒有val值
        }
        if(p1.val>p2.val){
            p3.next=p2;
            p3=p2;
            p2=p2.next;
        }
    }
        while(p1!=null){
           p3.next=p1;
            p3=p1;
            p1=p1.next;
        }
        while(p2!=null){
            p3.next=p2;
            p3=p2;
            p2=p2.next;
            
        }
    return pHead3.next;
    
}
module.exports = {
    Merge : Merge
};

問題17:操作給定的二叉樹,將其變換為源二叉樹的映象。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Mirror(root)
{
    // write code here
    if(root==null){
        return null;
    }
    if(root.left==null&&root.right==null){
        return root;
    }
//前序遍歷    用後序遍歷也可以
    var temp=root.left;
    root.left=root.right;
    root.right=temp;
    Mirror(root.left);
    Mirror(root.right);  
    
}

問題18:從上往下層次列印二叉樹節點

  解題思路:利用一個佇列進行層次遍歷,先把一個節點放到佇列中,然後再利用這個結點把它的左子結點和右子結點放到佇列中;然後再把該節點放到列印陣列中;迴圈的條件是佇列不為空

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function PrintFromTopToBottom(root)
{
    // write code here
     // write code here層序遍歷,是先判斷元素的左右子樹,再將頭節點出佇列
    var queue=[];
    var res=[];
    if(root!=null){//先判斷第一個不為空時把節點加入到佇列中
        queue.push(root);
    }
    while(queue.length!=0){//開始判斷一下佇列的元素
        var node=queue.shift();
        if(node.left!=null){//先判斷下有沒有左右子樹,有的話先把左右子樹節點加入到佇列
            queue.push(node.left);
        }
        if(node.right!=null){
            queue.push(node.right);
        } 
        res.push(node.val);
    }
    return res;
}
module.exports = {
    PrintFromTopToBottom : PrintFromTopToBottom
};

問題19 :和為S的兩個數字

function FindNumbersWithSum(array, sum)
{
    // write code here
       if(array==null){
            return null;
        }
        var left=0;
        var right=array.length-1;
        var curNum=0;
        var mulSum;
        var result=[];
        var min=Number.POSITIVE_INFINITY;
        var index1;
        var index2;
        var flag=false;
        while(left<right){
            
            curNum=array[left]+array[right];
            if(curNum==sum){
                flag=true;
                mulSum=array[left]*array[right];
                if(min>mulSum){
                min=mulSum;
                index1=left;
                index2=right;
            }
                left++;
                right--;
            }
            if(curNum<sum){ 
                left++;
            }
            if(curNum>sum){
                right--;
            }            
        }
    if(flag==true){
              result.push(array[index1]);
            result.push(array[index2]);
       
        return result;
    }
    return [];
    
    
}

問題20:和為S的連續正數子序列

function FindNumbersWithSum(array, sum)
{
    // write code here
       if(array==null){
            return null;
        }
        var left=0;
        var right=array.length-1;
        var curNum=0;
        var mulSum;
        var result=[];
        var min=Number.POSITIVE_INFINITY;
        var index1;
        var index2;
        var flag=false;
        while(left<right){
            
            curNum=array[left]+array[right];
            if(curNum==sum){
                flag=true;
                mulSum=array[left]*array[right];
                if(min>mulSum){
                min=mulSum;
                index1=left;
                index2=right;
            }
                left++;
                right--;
            }
            if(curNum<sum){ 
                left++;
            }
            if(curNum>sum){
                right--;
            }            
        }
    if(flag==true){
              result.push(array[index1]);
            result.push(array[index2]);
       
        return result;
    }
    return [];
    
    
}

問題21:將陣列按層次展開

var list = [1,2,[3,4],[5,6,[7,8],9],10,11]
		var res = [];
		function flatten(list, depth){
			if(depth == 0){
				for(var i = 0; i<list.length; i++){
					res.push(list[i]);
				}
				return;
			}
			for(var i = 0; i<list.length; i++){
				if(list[i] instanceof Array){
					flatten(list[i], depth - 1);
				}else{
					res.push(list[i]);
				}
			}
			return res;
		}

		console.log(flatten(list, 1));
		
		res = [];
		console.log(flatten(list, 2));

問題22:陣列去重

  方法1:先排序,然後將第一個元素先放進結果陣列中,從第二個起迴圈遍歷陣列,每次都和結果陣列的最後一個元素比較。

    function del(arr){
        var arr=arr.sort();
        
        var res=[arr[0]];//把第一個元素取出來
        for(var i=0;i<arr.length;i++){
            if(arr[i]!=res[res.length-1]){//每次都和結果陣列中的元素作比較
                res.push(arr[i]);
            }
        }
        return res;
    }
     var arr=[1,3,2,4,2,5,2,5];
     console.log(del(arr));

方法2:使用indexof方法    

function del(arr){
        var res=[];
        for(var i=0;i<arr.length;i++){
            if(res.indexOf(arr[i])==-1){
                res.push(arr[i]);
            }
        }

        return res;
    }

方法3:使用set()方法

    function quchong(arr){
        const s=new Set(arr);
        console.log(s);
    }
     var arr=[1,3,2,4,2,5,2,5];
     quchong(arr);

問題23:判斷單鏈表裡是否有環,以及其入口節點

   1判斷是否有環    

<script type="text/javascript">  
      const slow=pHead;//慢指標走一步
      const fast=pHead;//
      while(slow!=null&fast.next!=null){//沒有環的時候,快指標有可能跳出連結串列,所以讓fast的next不為空
        fast=fast.next.next;
        slow=slow.next;
        if(fast==slow){
            return true;
        }
      }
      return false;
     </script>

  2,找環的入口

     原理:從連結串列起點head開始到入口點的距離a,與從slow和fast的相遇點到入口點的距離相等。(別人推匯出來的)

    <script type="text/javascript">  
      const slow=pHead;//慢指標走一步
      const fast=pHead;//
      while(slow!=null && fast.next!=null){
           fast=fast.next.next;
           slow=slow.next;
           if(slow==fast)  break;
      }
      if(slow==null || fast.next==null) return null;//表示連結串列沒有環
      const p1=pHead;//一個指向連結串列的起點
      const p2=slow;//一個指向快慢指標相遇點
      while(p1!=p2){
        p1=p1.next;
        p2=p2.next;
      }
      return p1;//p1和p2走了一樣的距離並相遇時便是入口點
     </script>

3 如果存在環,求環上的節點數

記錄下相遇時的節點,並且存入臨時變數temp中,然後慢指標繼續往下走slow=slow.next,一直到slow=temp,此時經過的步數就是環的長度。

     <script type="text/javascript">  
      const slow=pHead;//慢指標走一步
      const fast=pHead;//
      const step=1;
      while(slow!=null && fast.next!=null){
           fast=fast.next.next;
           slow=slow.next;
           if(fast==slow){
            const temp=slow;//找到了相遇點,並且把它記錄下來
            slow=slow.next;
            break;
           }
      }
      while(slow!=temp){//slow一直走到temp的位置,slow從相遇點開始走的步數就是環的長度
         slow=slow.next;
         step++;
     }
     return step;
     </script>

4 如果存在環,求出連結串列的長度

  解決思路:連結串列的長度=起點到入口的距離+環的長度

5 求出一個環上距離任意一個節點最遠的點

問題:構建乘積陣列

將陣列B分開,分成左下三角和右上三角;左下三角c[i]=c[i-1]*A[i-1].右上三角 D[i]=D[i+1]*A[i+1];

問題24:刪除有序連結串列中重複的節點,重複節點都不保留,返回頭指標。

    用當前cur指標和pre前驅指標,當兩者相鄰的時候說明cur還沒有找到重複元素,不相鄰的時候說明pre和cur之間有了部分相同的元素。

function ListNode(x){
    this.val = x;
    this.next = null;
}
function deleteDuplication(pHead)
{
    // write code here
    if(pHead==null){
        return null;
    }
    var node=new ListNode(-1);
    node.next=pHead;
    var pre=node;
    var cur=node.next;
    while(cur!=null){
        while(cur.next!=null && cur.val==cur.next.val){//一定要注意cur.next!=null
            cur=cur.next;
        }
        if(pre.next!=cur){//cur找到重複元素往後移動了,才不和Pre挨著了
            pre.next=cur.next;
            cur=cur.next;
        }else{//當還沒遇到重複元素時,既pre 和cur還挨著的時候
            pre=cur;//只有先讓pre移動到cur,cur再移動,才能保證pre永遠比cur慢一步
            cur=cur.next;            
        }
    }
    return  node.next;
    
}

問題25:二叉樹的下一個結點。給定一課二叉樹和其中的一個結點,如何找出中序遍歷順序的下一個結點?樹中的結點除了有兩個分別指向左右子結點的指標以外,還有一個指向父結點的指標。

該題的解題思路就是:

分兩種情況:1.該節點有右子樹,則右子樹的最最左結點是所要找的節點

                      2.該節點沒有右子樹,則一直往上找,直到找到一個結點是其父結點的左子結點,則該父結點就是所要找的節點

/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    // write code here
    //分三種情況:
    //1.當該節點有右子樹,則右子樹的最左子節點是所要找的節點
    //2.當該節點沒有右子樹,則找當前節點是其父節點的左子結點的節點
   
    if(pNode==null){
        return null;
    }
    if(pNode.right!=null){//情況1
        var pNode=pNode.right;
        while(pNode.left!=null){
            pNode=pNode.left;
        }
        return pNode;
    }
    while(pNode.next!=null){//情況2
        if(pNode.next.left==pNode){
            return pNode.next;
        }
        pNode=pNode.next;
    }
   }

問題26:實現一個函式,用來判斷一棵二叉樹是不是對稱的。如果一棵二叉樹和它的映象一樣,那麼它是對稱的。

function isSymmetrical2(root1,root2){
    if(root1 == null && root2 == null){
        return true;
    }
    if(root1 == null || root2 == null){
        return false;
    }
    if(root1.val != root2.val){
        return false;
    }
    return  isSymmetrical2(root1.left,root2.right) && isSymmetrical2(root1.right,root2.left); 
}
function isSymmetrical(pRoot)
{
    // write code here
    return isSymmetrical2(pRoot,pRoot);
}

問題27:按之字形狀從上到下列印二叉樹。第一行按從左到右的順序列印,第二行按從右到左的順序列印,接下來的依次交換

   解題思路:使用兩個棧來操作,stack1用來暫存奇數行的節點,stack2用來暫存偶數行的節點。當奇數行的時候,將奇數行元素加入結果陣列的同時,還把下一行的元素按照先左子節點後右子節點的順序加入到stack2中;當偶數行的時候,將偶數行元素加入結果陣列的同時,還把下一行的元素按照先右子節點後左子節點的順序加入到stack1中;

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Print(pRoot)
{
    // write code here
    var lists=new Array();//存放結果
    if(pRoot==null){
        return lists;
    }
    
    var stack1=[];//存放奇數行
    var stack2=[];//存放偶數行
    stack1.push(pRoot);
    var i=1;//層數
    while(stack1.length!=0 || stack2.length!=0){
        var list=new Array();
        if((i&1)==1){//當是奇數行的時候
            while(stack1.length!=0){
            var temp=stack1[stack1.length-1];//用一陣列記錄下,一直是從後往前push的
            list.push(temp.val);
            stack1.pop();
            if(temp.left!=null){
               //把下一行(偶數行)的數儲存在stack2中,因為是從右往左,所以在棧中先新增左子節點
                stack2.push(temp.left);
            }
            if(temp.right!=null){
                stack2.push(temp.right);
            }
        }
        }else{//當是偶數行的時候
            while(stack2.length!=0){
                var temp=stack2[stack2.length-1];
                list.push(temp.val);
                stack2.pop();
                //因為奇數行是從左往右列印,所以在棧中先新增右子節點再新增左子節點
                if(temp.right!=null){
                    stack1.push(temp.right);
                }
                if(temp.left!=null){
                    stack1.push(temp.left);
                }
            }
        }
        i++;
        lists.push(list);       
        
    }   
    return lists;
    
}

問題28:從上到下把二叉樹列印成多行。

解題思路: 在層序遍歷+佇列的基礎上,判斷每層的節點數;先把每層的節點放進陣列中,然後再把這個陣列放在結果陣列中。 

function Print(pRoot)
{
    // write code here
    if(pRoot==null){
        return [];
    }
    var queue=[];
    var res=[];
    queue.push(pRoot);
    while(queue.length!=0){
        var len=queue.length;//一定要在這個地方標記一下queue的長度,以免queue新增的時候篡改
        var tempArr=[];//用來臨時儲存一行的元素
        for(var i=0;i<len;i++){
            var node = queue.shift();//會自動的減掉queue的長度
            tempArr.push(node.val);//將一行放在一個臨時陣列中
            if(node.left!=null){
                queue.push(node.left);
             }
            if(node.right!=null){
                queue.push(node.right);
             }
        }        
        res.push(tempArr);
    }   
    
    return res;
}

問題29 序列化一棵二叉樹

  解題思路:先將一個棵樹深度遍歷(前序遍歷)到一個數組,其中將'a’作為樹的葉子節點;然後再前序遍歷反序列化

 function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} 
let arr=[]
function Serialize(pRoot)
{
    // write code here
    if(pRoot!=null){//深度優先遍歷
        arr.push(pRoot.val);
        Serialize(pRoot.left);
        Serialize(pRoot.right);         
    }else{
        arr.push('a');//把a當做葉子節點        
    }
    
}
function Deserialize()
{
    // write code here
    var root=null;
    if(arr.length<0){
        return null
    };//接上一種情況,當arr裡沒有元素的時候
    let node=arr.shift();
    if(typeof node == 'number'){
        root=new  TreeNode(node);//將摘下來的node傳給一個樹節點
        root.left=Deserialize();
        root.right=Deserialize();
        
    }
    return root;    
}

問題30  給定一棵二叉搜尋樹,請找出其中的第k小的結點。例如, (5,3,7,2,4,6,8)    中,按結點數值大小順序第三小結點的值為4。

  解題思路:中序遍歷+計數。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function KthNode(pRoot, k)
{
    // write code here
     if(pRoot==null || k==0){
        return null;
    }
   function KthNodeCore(pRoot){//對這個函式進行遞迴
        let target = null;//目標值
        if(pRoot.left != null){ //中序遍歷先遍歷左子樹
            target = KthNodeCore(pRoot.left, k);
        }
        if(target == null){//當左子樹遍歷不到的時候,遍歷根節點
            if(k == 1){//k等於1說明找到了
                target = pRoot;
            }
            k--; 
        }
        if(target == null && pRoot.right != null){//當左子樹和根都沒有找到的話,遍歷右子樹
            target = KthNodeCore(pRoot.right, k);
        }
        return target;
    }
    return KthNodeCore(pRoot);
}

 問題:陣列中重複的數字

由於數組裡的所有數字都在0到n-1,也就是值也在陣列的下標範圍裡。

我們可以這樣做,通俗來講,就是把陣列中的每個值放到對應的下標的位置上。(數歸其標)

  1. 把當前序列當成是一個下標和下標對應值是相同的陣列;
  2. 遍歷陣列,判斷當前位的值和下標是否相等: 2.1. 若相等,則遍歷下一位; 2.2. 若不等,則將當前位置i上的元素和a[i]位置上的元素比較:若它們相等,則成功,即找到了重複的值!若不等,則將它們兩交換。換完之後a[i]位置上的值和它的下標是對應的,但i位置上的元素和下標並不一定對應;重複2.2的操作,直到當前位置i的值也為i,將i向後移一位,再重複2.
function duplicate(numbers, duplication)
{
    // write code here
    //這裡要特別注意~找到任意重複的一個值並賦值到duplication[0]
    //函式返回True/False
      for(var i=0;i<numbers.length;i++){
        while(i!=numbers[i]){//每次都是把元素放在它對應的位置
            if(numbers[i]==numbers[numbers[i]]){
                duplication[0]=numbers[i];
                return true;
            }
            var temp=numbers[i];
            numbers[i]=numbers[temp];
            numbers[temp]=temp;
        }
    }
    return false;
}