【剑指offer】21-30题

21.定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

思路:定义两个栈,一个存放入的值。另一个存最小值。

代码实现

public void push(int node) {
    stack1.push(node);
    if (stack2.isEmpty()) {
        stack2.push(node);
    }else {
        if (stack2.peek() > node) {
            stack2.push(node);
        }
    }
}

public void pop() {
    if (stack1.pop() == stack2.peek()) {
        stack2.pop();
    }
}

public int top() {
    return stack1.peek();
}

public int min() {
    return stack2.peek();
}

22.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:用栈来压入弹出元素,相等则出栈。

代码实现

public boolean IsPopOrder(int [] pushA,int [] popA) {
    if (pushA == null || popA == null) {
        return false;
    }
    Stack<Integer> stack = new Stack<>();
    int index = 0;

    for (int i = 0; i < pushA.length; i++) {
        stack.push(pushA[i]);
        while (!stack.isEmpty() && stack.peek() == popA[index]) {
            stack.pop();
            index++;
        }
    }
    return stack.isEmpty();
}

23.从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:利用队列(链表)辅助实现。

代码实现

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<>();
    if (root == null) {
        return list;
    }
    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        list.add(node.val);
        if (node.left != null) {
            queue.addLast(node.left);
        }
        if (node.right != null) {
            queue.addLast(node.right);
        }
    }
    return list;
}

24.输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路:先找到右子树的开始位置,然后分别进行左右子树递归处理。

代码实现

   public boolean VerifySquenceOfBST(int[] sequence) {
    if (sequence == null || sequence.length == 0)
        return false;
    int rstart = 0;
    int length = sequence.length;

    for (int i = 0; i < length - 1; i++) {
        if (sequence[i] < sequence[length - 1])
            rstart++;
    }

    if (rstart == 0) {
        VerifySquenceOfBST(Arrays.copyOfRange(sequence,0,length-1));
    }else {
        for (int i = rstart; i < length - 1; i++) {
            if (sequence[i] <= sequence[length - 1]) {
                return false;
            }
        }
        VerifySquenceOfBST(Arrays.copyOfRange(sequence,0,rstart));
        VerifySquenceOfBST(Arrays.copyOfRange(sequence,rstart,length - 1));
    }
    return true;
}

25.输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路:先保存根节点,然后分别递归在左右子树中找目标值,若找到即到达叶子节点,打印路径中的值

代码实现

public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
    if(root == null)
        return resultList;
    list.add(root.val);
    target -= root.val;

    if(target == 0 && root.left == null && root.right == null){
        resultList.add(new ArrayList<>(list));
    }else {
        FindPath(root.left,target);
        FindPath(root.right,target);
    }
    //每返回上一层一次就要回退一个节点
    list.remove(list.size()-1);
    return resultList;
}

26.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路:先复制链表的next节点,将复制后的节点接在原节点后,然后复制其它的节点,最后取偶数位置的节点(复制后的节点)。

代码实现

public RandomListNode Clone2(RandomListNode pHead) {
    if(pHead == null)
        return null;
    RandomListNode head = new RandomListNode(pHead.label) ;
    RandomListNode temp = head ;

    while(pHead.next != null) {
        temp.next = new RandomListNode(pHead.next.label) ;
        if(pHead.random != null) {
            temp.random = new RandomListNode(pHead.random.label) ;
        }
        pHead = pHead.next ;
        temp = temp.next ;
    }
    return head ;
}

27.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路:定义一个链表的尾节点,递归处理左右子树,最后返回链表的头节点

代码实现

public TreeNode Convert(TreeNode pRootOfTree) {
    TreeNode lastlist = covertNode(pRootOfTree,null);
    TreeNode pHead = lastlist;
    while (pHead != null && pHead.left != null) {
        pHead = pHead.left;
    }
    return pHead;
}

public TreeNode covertNode(TreeNode root, TreeNode lastlist) {
    if (root == null)
        return null;
    TreeNode cur = root;
    if (cur.left != null) {
        lastlist = covertNode(cur.left,lastlist);
    }
    cur.left = lastlist;
    if (lastlist != null) {
        lastlist.right = cur;
    }
    lastlist = cur;
    if (cur.right != null) {
        lastlist = covertNode(cur.right,lastlist);
    }
    return lastlist;
}

28.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

思路:将当前位置的字符和前一个字符位置交换,递归。

代码实现

public ArrayList<String> Permutation(String str) {
    ArrayList<String> result = new ArrayList<String>() ;
    if(str == null || str.length() == 0)
        return result;
    char[] chars = str.toCharArray() ;
    TreeSet<String> temp = new TreeSet<>() ;
    Permutation(chars, 0, temp);
    result.addAll(temp) ;
    return result ;
}

public void Permutation(char[] chars, int index, TreeSet<String> result) {
    if(chars == null || chars.length == 0 )
        return ;
    if (index < 0 || index > chars.length - 1)
        return;
    if(index == chars.length-1) {
        result.add(String.valueOf(chars)) ;
    }else {
        for(int i=index ; i<=chars.length-1 ; i++) {
            swap(chars, index, i) ;
            Permutation(chars, index+1, result);
            // 回退
            swap(chars, index, i) ;
        }
    }
}

public void swap(char[] c, int a,int b) {
    char temp = c[a];
    c[a] = c[b];
    c[b] = temp;
}

29.数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字

思路:将首次出现的数count+1,与之后的数进行比较,相等则+1,否则—1,最后进行校验是否超过长度的一半。

代码实现

public int MoreThanHalfNum_Solution(int [] array) {
    int maxCount = array[0];
    int number = array[0];
    int count = 1;

    for (int i = 1; i < array.length; i++) {
        if (number != array[i]) {
            if (count == 0) {
                number = array[i];
                count = 1;
            }else {
                count--;
            }
        }else {
            count++;
        }

        if (count == 1) {
            maxCount = number;
        }
    }
    // 验证
    int num = 0;
    for (int j = 0; j < array.length; j++) {
        if (array[j] == maxCount) {
            num++;
        }
    }

    if (num * 2 > array.length) {
        return maxCount;
    }
    return 0;
}

30.输入n个整数,找出其中最小的K个数。

思路:先将前K个数放入数组,进行堆排序,若之后的数比它还小,则进行调整

代码实现

public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
    ArrayList<Integer> list = new ArrayList<>();
    if (input == null || k <= 0 || k > input.length) {
        return list;
    }
    int[] kArray = Arrays.copyOfRange(input,0,k);
    // 创建大根堆
    buildHeap(kArray);

    for(int i = k; i < input.length; i++) {
        if(input[i] < kArray[0]) {
            kArray[0] = input[i];
            maxHeap(kArray, 0);
        }
    }

    for (int i = kArray.length - 1; i >= 0; i--) {
        list.add(kArray[i]);
    }

    return list;
}

public void buildHeap(int[] input) {
    for (int i = input.length/2 - 1; i >= 0; i--) {
        maxHeap(input,i);
    }
}

private void maxHeap(int[] array,int i) {
    int left=2*i+1;
    int right=left+1;
    int largest=0;

    if(left < array.length && array[left] > array[i])
        largest=left;
    else
        largest=i;

    if(right < array.length && array[right] > array[largest])
        largest = right;

    if(largest != i) {
        int temp = array[i];
        array[i] = array[largest];
        array[largest] = temp;
        maxHeap(array, largest);
    }
}

未完待续。。。。。。

猜你喜欢

转载自blog.csdn.net/baiye_xing/article/details/78428347