劍指Offer筆記(三)

1.3.18 定義一個棧的數據結構,實現min(找出棧中最小的元素),pop,add函數,並且要求三個函數的時間複雜度都是O(1)

package Chapter4;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

public class HasMinFStack {
    LinkedList<Integer> minStack = null;
    LinkedList<Integer> stack = null;
    public HasMinFStack(){
        minStack = new LinkedList<>();
        stack = new LinkedList<>();
    }
    public void add(int num){
        if(minStack.isEmpty() && stack.isEmpty()){
            stack.addLast(num);
            minStack.addLast(num);
        }else{
            stack.add(num);
            if(minStack.getLast() >= num){
                minStack.addLast(num);
            }else{
                minStack.addLast(minStack.getLast());
            }
        }
    }
    public int pop() throws Exception{
        if(!stack.isEmpty() && !minStack.isEmpty()){
            minStack.removeLast();
            return stack.removeLast();
        }else{
            throw new Exception("this stack is empty");
        }
    }
    public int getMin() throws Exception{
        if(!minStack.isEmpty()){
            return minStack.getLast();
        }else{
            throw new Exception("this stack is empty");
        }
    }
}

測試類

package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Test;

import Chapter4.HasMinFStack;

public class HasMinFStackTest {

    @Test
    public void test() {
        HasMinFStack hasMinFStack = new HasMinFStack();
        hasMinFStack.add(10);
        hasMinFStack.add(2);
        hasMinFStack.add(5);
        hasMinFStack.add(1);
        hasMinFStack.add(1);
        hasMinFStack.add(3);
        hasMinFStack.add(4);
        try {
            System.out.println("min = "+hasMinFStack.getMin());
            System.out.println("pop = "+hasMinFStack.pop());
            System.out.println("pop = "+hasMinFStack.pop());
            System.out.println("pop = "+hasMinFStack.pop());
            System.out.println("min = "+hasMinFStack.getMin());
            System.out.println("pop = "+hasMinFStack.pop());
            System.out.println("min = "+hasMinFStack.getMin());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
//====輸出======
/*
min = 1
pop = 4
pop = 3
pop = 1
min = 1
pop = 1
min = 2
*/

1.3.19 輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否是第一個序列的彈出順序。

package Chapter4;

import java.util.LinkedList;

public class IsTrueOrder {
    private static LinkedList<Integer> stack = new LinkedList<>();

    public static boolean isTrueOrder(int[] pushOrder, int[] popOrder){
        boolean result = false;
        if(pushOrder == null || popOrder == null)
            return result;
        stack.clear();
        int i = 0;
        int j = 0;
        //第一步,一開始是空棧,所以先把第一個出棧元素(包括)之前的元素都入棧,並且把i指到入棧順序的下一個位置。
        //push: 1,2,3,4,5
        //pop: 4,5,3,2,1
        //stack: 1,2,3,4   push[i] = 5  pop[j] = 4
        for(;i<pushOrder.length; i++){
            stack.addLast(pushOrder[i]);
            if(pushOrder[i] == popOrder[j]){
                i++;
                break;
            }
        }
        //2 如果push還沒有全部入棧,則將push想辦法全部入棧
        //  2.1 當然,在這部分:
        //      如果棧頂元素與pop[j]的元素相同,則移除棧頂元素 j++ 
        //      如果棧頂元素與pop[j]的元素不同,則把push還沒有入棧的元素(所以上面進行了i++)一直入棧,直到棧頂元素與pop[j]元素相同
        //  一直循環2.1步
        //執行完這步,就會將push全部入棧
        while(i < pushOrder.length){
            if(stack.getLast() == popOrder[j]){
                stack.removeLast();
                j++;
            }else{
                for(;i<pushOrder.length; i++){
                    stack.addLast(pushOrder[i]);
                    if(pushOrder[i] == popOrder[j]){
                        i++;
                        break;
                    }
                }
            }
        }
        //檢查棧是不是爲空,如果不爲空,則判斷棧頂與pop[j]是否相同,如果相同:j++,棧彈出之後再判斷棧頂與pop[j]是否相同,直到不同return flase 或者棧空return true
        while(!stack.isEmpty()){
            if(stack.getLast() == popOrder[j]){
                stack.removeLast();
                j++;
            }else{
                result = false;
                break;
            }
        }
        if(stack.isEmpty()){
            result = true;
        }
        return result; 
    }
}

測試類

package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Test;

import Chapter4.IsTrueOrder;

public class IsTrueOrderTest {

    @Test(timeout=2000)
    public void test() {
        int[] pushOrder = {1,2,3,4,5};
        int[] popOrder = {4,5,3,2,1};
        int[] popOrder2 = {4,3,5,1,2};
        assertEquals(true, IsTrueOrder.isTrueOrder(pushOrder, popOrder));
        assertEquals(false, IsTrueOrder.isTrueOrder(pushOrder, popOrder2));
    }

}

1.3.20 輸入一個二叉樹和一個整數,打印出二叉樹中某一路徑所以節點的和等於該整數的路徑。

//測試用例
package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import Chapter2.BinaryTreeNode;
import Chapter4.PathSum;

public class PathSumTest {
    private BinaryTreeNode root = null;
    @Before
    public void initBinaryTree(){
        root = new BinaryTreeNode();
        root.setValue(10);

        root.leftNode = new BinaryTreeNode();
        root.leftNode.setValue(5);
        root.rightNode = new BinaryTreeNode();
        root.rightNode.setValue(12);

        root.leftNode.leftNode = new BinaryTreeNode();
        root.leftNode.leftNode.setValue(4);
        root.leftNode.rightNode = new BinaryTreeNode();
        root.leftNode.rightNode.setValue(7);
    }
    @Test
    public void test() {
        PathSum.PathSumToANum(22, root);
    }

}



//========================================

//實現代碼
package Chapter4;

import java.util.ArrayList;

import Chapter2.BinaryTreeNode;
import Chapter2.BinaryTreeNodeCode;

public class PathSum {
    public static void PathSumToANum(int num, BinaryTreeNode root){
        ArrayList<BinaryTreeNodeCode> stack = new ArrayList<>();
        if(root != null){
            stack.add(new BinaryTreeNodeCode(root, 1));
        }
        while(!stack.isEmpty()){
            BinaryTreeNodeCode peek = stack.get(stack.size()-1);
            if(peek.getCode() == 1){
                peek.setCode(2);
                if(peek.getBinaryTreeNode().leftNode != null){
                    stack.add(new BinaryTreeNodeCode(peek.getBinaryTreeNode().leftNode, 1));
                }
            }else if(peek.getCode() == 2){
                peek.setCode(3);
                if(peek.getBinaryTreeNode().rightNode != null){
                    stack.add(new BinaryTreeNodeCode(peek.getBinaryTreeNode().rightNode, 1));
                }
            }else{
                int sum = 0;
                for(BinaryTreeNodeCode node:stack){
                    sum += node.getBinaryTreeNode().getValue();
                }
                if(sum == num){
                    for(BinaryTreeNodeCode node:stack){
                        System.out.print(node.getBinaryTreeNode().getValue()+" ");
                    }
                    System.out.println();
                }

                stack.remove(stack.size()-1);

            }
        }

    }
}

1.3.21 複雜鏈表的複製

//================測試用例=================
package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import Chapter4.CloneComplexList;
import Chapter4.ComplexNode;

public class ComplexNodeTest {
    private ComplexNode oldNode = null;
    @Before
    public void initOldNode(){
        oldNode = new ComplexNode();
        oldNode.setValue(1);

        oldNode.next = new ComplexNode();
        oldNode.next.setValue(2);

        oldNode.next.next = new ComplexNode();
        oldNode.next.next.setValue(3);
        oldNode.sibling = oldNode.next.next;

        oldNode.next.next.next = new ComplexNode();
        oldNode.next.next.next.setValue(4);
        oldNode.next.next.next.sibling = oldNode.next;

        //1 -> 2 -> 3 -> 4
        //1 -> 3
        //4 -> 2
    }
    @Test(timeout=2000)
    public void test() {
        ComplexNode newRoot = CloneComplexList.cloneComplexList(oldNode);
        System.out.println(oldNode.next == newRoot.next);
        ComplexNode nowNewNode = newRoot;
        ComplexNode nowOldNode = oldNode;

        System.out.println("====== new List ======");
        while(nowNewNode != null){
            System.out.println(nowNewNode+" ; "+nowNewNode.sibling);
            nowNewNode = nowNewNode.next;
        }
        System.out.println("====== old List ======");
        while(nowOldNode != null){
            System.out.println(nowOldNode+" ; "+nowOldNode.sibling);
            nowOldNode = nowOldNode.next;
        }
    }

}


//=================輸出==================
map : Chapter4.ComplexNode@44287d38----Chapter4.ComplexNode@4aef9bcd
map : Chapter4.ComplexNode@4ed01648----Chapter4.ComplexNode@bd291f6
map : Chapter4.ComplexNode@c94ec09----Chapter4.ComplexNode@3a933fa5
map : Chapter4.ComplexNode@743f1ce9----Chapter4.ComplexNode@6bfd6eb9
false
====== new List ======
Chapter4.ComplexNode@4aef9bcd ; Chapter4.ComplexNode@3a933fa5
Chapter4.ComplexNode@bd291f6 ; null
Chapter4.ComplexNode@3a933fa5 ; null
Chapter4.ComplexNode@6bfd6eb9 ; Chapter4.ComplexNode@bd291f6
====== old List ======
Chapter4.ComplexNode@44287d38 ; Chapter4.ComplexNode@c94ec09
Chapter4.ComplexNode@4ed01648 ; null
Chapter4.ComplexNode@c94ec09 ; null
Chapter4.ComplexNode@743f1ce9 ; Chapter4.ComplexNode@4ed01648


//=================實現代碼 (第一種方法) ===============
package Chapter4;

import java.util.HashMap;
import java.util.Map;

import Chapter1.Node;

public class CloneComplexList {
    public static Node cloneList(Node root){
        if(root == null){
            return null;
        }

        Node newRoot = new Node();

        Node nowNewNode = newRoot;
        Node nowOldNode = root;

        while(nowOldNode != null){
            nowNewNode.setValue(nowOldNode.getValue());

            nowOldNode = nowOldNode.next;
            if(nowOldNode != null){
                nowNewNode.next = new Node();
                nowNewNode = nowNewNode.next;
            }
        }

        return newRoot;
    }

    public static ComplexNode cloneComplexList(ComplexNode root){
        if(root == null){
            return null;
        }
        ComplexNode newRoot = new ComplexNode();
        Map<ComplexNode, ComplexNode> nodeMap = new HashMap<>();

        /*
         * 先複製基礎鏈表節點
         */
        {

            ComplexNode nowNewNode = newRoot;
            ComplexNode nowOldNode = root;

            while(nowOldNode != null){
                nowNewNode.setValue(nowOldNode.getValue());
                System.out.println("map : "+nowOldNode+"----"+nowNewNode);
                nodeMap.put(nowOldNode, nowNewNode);

                nowOldNode = nowOldNode.next;
                if(nowOldNode != null){
                    nowNewNode.next = new ComplexNode();
                    nowNewNode = nowNewNode.next;
                }
            }
        }

        //開始複製複雜節點
        {
            ComplexNode nowOldNode = root;
            ComplexNode nowNewNode = newRoot;
            while(nowOldNode != null){
                if(nowOldNode.sibling != null){
                    nowNewNode.sibling = nodeMap.get(nowOldNode.sibling);
                }
                nowOldNode = nowOldNode.next;
                nowNewNode = nowNewNode.next;
            }
        }

        return newRoot;
    }
}

1.3.22 將二叉排序樹轉換成雙向鏈表

//===========測試用例===========
package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import Chapter2.BinaryTreeNode;
import Chapter4.BinarySortTree;
import Chapter4.TwowayNode;

public class TwowayNodeTest {
    private BinaryTreeNode root;
    @Before
    public void initSortedBinaryTree(){
        root = new BinaryTreeNode();
        root.setValue(10);

        root.leftNode = new BinaryTreeNode();
        root.leftNode.setValue(6);
        root.rightNode = new BinaryTreeNode();
        root.rightNode.setValue(14);

        root.leftNode.leftNode = new BinaryTreeNode();
        root.leftNode.leftNode.setValue(4);
        root.leftNode.rightNode = new BinaryTreeNode();
        root.leftNode.rightNode.setValue(8);
        root.rightNode.leftNode = new BinaryTreeNode();
        root.rightNode.leftNode.setValue(12);
        root.rightNode.rightNode = new BinaryTreeNode();
        root.rightNode.rightNode.setValue(16);

    }
    @Test
    public void test() {
        BinaryTreeNode listHead = BinarySortTree.ConverByTreeRoot(root);
        System.out.println("head : "+listHead);
        while(listHead!=null){
            System.out.println(listHead+":"+listHead.getValue()+" ; "+listHead.leftNode+" ; "+listHead.rightNode);
            listHead = listHead.rightNode;
        }
    }

}


//===============輸出結果================
head : Chapter2.BinaryTreeNode@4d405ef7
Chapter2.BinaryTreeNode@4d405ef7:4 ; null ; Chapter2.BinaryTreeNode@6193b845
Chapter2.BinaryTreeNode@6193b845:6 ; Chapter2.BinaryTreeNode@4d405ef7 ; Chapter2.BinaryTreeNode@2e817b38
Chapter2.BinaryTreeNode@2e817b38:8 ; Chapter2.BinaryTreeNode@6193b845 ; Chapter2.BinaryTreeNode@c4437c4
Chapter2.BinaryTreeNode@c4437c4:10 ; Chapter2.BinaryTreeNode@2e817b38 ; Chapter2.BinaryTreeNode@433c675d
Chapter2.BinaryTreeNode@433c675d:12 ; Chapter2.BinaryTreeNode@c4437c4 ; Chapter2.BinaryTreeNode@3f91beef
Chapter2.BinaryTreeNode@3f91beef:14 ; Chapter2.BinaryTreeNode@433c675d ; Chapter2.BinaryTreeNode@1a6c5a9e
Chapter2.BinaryTreeNode@1a6c5a9e:16 ; Chapter2.BinaryTreeNode@3f91beef ; null


//=================實現代碼===================
package Chapter4;

import Chapter2.BinaryTreeNode;

public class BinarySortTree {
    public static BinaryTreeNode ConverByTreeRoot(BinaryTreeNode root){

        BinaryTreeNode lastNodeInList = null;
        lastNodeInList = conver(root, lastNodeInList);

        BinaryTreeNode headRoot = lastNodeInList;
        while(headRoot != null && headRoot.leftNode != null){
            headRoot = headRoot.leftNode;
        }
        return headRoot;
    }
    /*
     * 爲什麼要返回lastNodeInList:
     *  因爲java在傳遞參數的時候是複製機制
     *  又因爲傳遞的是引用,所以在棧中複製了另外一個引用B,跟實參A指向一個堆內存
     *  當B進行移動的時候,A是不移動的,所以函數裏B的移動不能影響A
     *  所以每次都將移動的B重新傳遞給A
     */
    private static BinaryTreeNode conver(BinaryTreeNode root, BinaryTreeNode lastNodeInList){
        if(root == null){
            return null;
        }
        BinaryTreeNode currentNode = root;
        if(currentNode.leftNode != null){
            lastNodeInList = conver(currentNode.leftNode, lastNodeInList);
        }

        currentNode.leftNode = lastNodeInList;
        if(lastNodeInList != null)
            lastNodeInList.rightNode = currentNode;
        lastNodeInList = currentNode;

        if(currentNode.rightNode != null){
            lastNodeInList = conver(currentNode.rightNode, lastNodeInList);
        }

        return lastNodeInList;
    }
}

1.3.23 輸入一個字符串,打印出該字符串中字符的所有排列

//===========測試用例============
package test.Chapter4;

import static org.junit.Assert.*;

import org.junit.Test;

import Chapter4.SortString;

public class SortStringTest {

    @Test
    public void test() {
        SortString.sortString("abc");
    }

}


//===========輸出==============
abc
acb
cab
cba
abc
acb


//==========實現代碼============
package Chapter4;

public class SortString {
    public static void sortString(String str){
        if(str == null){
            return;
        }
        char[] chars = str.toCharArray();
        printString(chars, 0);
    }
    private static void printString(char[] chars, int pos){
        if(pos == chars.length){
            System.out.println(new String(chars));
            return;
        }
        for(int i = pos; i < chars.length; i++){
            char temp = chars[pos];
            chars[pos] = chars[i];
            chars[i] = temp;
            printString(chars, pos+1);
        }
    }
}

1.3.24 找出數組中出現次數超過一半的數字

package Chapter5;

public class FindMoreNum {
    public static int findNumGrowMoreHalf(int[] nums) throws Exception{
        if(nums == null){
            throw new Exception("the nums can't == null");
        }
        int key = nums[0];
        int count = 1;
        for(int i = 1; i < nums.length; i++){
            if(nums[i] != key){
                count--;
            }
            if(count == 0){
                key = nums[i];
                count = 1;
            }
        }
        return key;
    }
    public static void main(String[] args) {
        int[] t1 = {1,2,3,2,2,2,5,4,2};
        int[] t2 = {1,1,1,1,2,2,2,2,2};
        int[] t3 = {1,2,1,2,1,2,1,2,1};
        int[] t4 = null;
        try {
            System.out.println(findNumGrowMoreHalf(t1));
            System.out.println(findNumGrowMoreHalf(t2));
            System.out.println(findNumGrowMoreHalf(t3));
            System.out.println(findNumGrowMoreHalf(t4));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//======輸出=======
2
2
1
java.lang.Exception: the nums can't == null
    at Chapter5.FindMoreNum.findNumGrowMoreHalf(FindMoreNum.java:6)
    at Chapter5.FindMoreNum.main(FindMoreNum.java:30)

1.3.25 找出最小的K個數

package Chapter5;

import java.util.Comparator;
import java.util.TreeSet;

public class FindMinimumK {
    /*
    本方法用java提供的TreeSet實現,TreeSet默認使用紅黑樹實現(存數是有序的),所以添加,刪除,查找一個節點複雜度是O(logn) 所以整個代碼的複雜度就是klogn
    */
    public static void findMininumKNums(int[] nums, int k){
        TreeSet<Integer> treeSet = new TreeSet<>();

        for(int n:nums){
            treeSet.add(n);
        }

        for(int i = 0; i < k; i++)
            System.out.println(treeSet.pollFirst());
    }
    public static void main(String[] args) {
        int[] a = {4,5,1,6,2,7,3,8};
        findMininumKNums(a, 3);
    }
}

//====輸出=======
/*
1
2
3
*/

1.3.26 輸入一個正整數數組,把數組裏的所有數字拼接成一個數,打印出能拼接出的所有數字鐘最小的一個

package Chapter5;

import java.util.Arrays;
import java.util.Comparator;

public class SortnumsToMininum {
    public static void printTheMinOrder(Integer[] args) throws Exception{
        if(args == null){
            throw new Exception("the parameter can's be null");
        }
        Integer[] temp = Arrays.copyOf(args, args.length);
        Arrays.sort(temp, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                int a = Integer.parseInt(o1+""+o2);
                int b = Integer.parseInt(o2+""+o1);
                if(a > b){
                    return 1;
                }else if(a < b){
                    return -1;
                }else{
                    return 0;
                }
            };
        });
        for(int num:temp){
            System.out.print(num);
        }
        System.out.println();
    }
    public static void main(String[] args) {
        Integer[] num = {321,32,3};
        Integer[] num2 = {3,321,32};
        Integer[] num3 = {3,2,1};
        try {
            printTheMinOrder(num);
            printTheMinOrder(num2);
            printTheMinOrder(num3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//=======輸出=======
/*
321323
321323
123
*/

博客地址遷移至 int32.me

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章