【剑指OFFER-二刷】

反转链表

输入一个链表,反转链表后,输出链表的所有元素。

不借助任何多余空间,代码如下:

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head == null)
            return null;

        ListNode left = head;
        ListNode current = head;
        ListNode right = head.next;

        while(current.next != null) {
            current.next = right.next;
            right.next = left;
            left = right;
            right = current.next;
        }
        return left;
    }
}

重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

一定要注意确定前后界限,可以用个例子去试。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre == null || in == null)
            return null;

        return reConstructBinaryTree(pre, in, 0, pre.length, 0, in.length);
    }
    public TreeNode reConstructBinaryTree(int[] pre, int[] in, int preS, int preE, int inS, int inE) {
        if(preE <= preS || inE <= inS)
            return null;

        int i = inS;
        int count = 0;
        for(; i < inE && in[i] != pre[preS]; i++) {count++;}

        TreeNode root = new TreeNode(pre[preS]);
        root.left = reConstructBinaryTree(pre, in, preS+1, preS+1+count, inS, inS+count);
        root.right = reConstructBinaryTree(pre, in, preS+1+count, preE, inS+count+1, inE);

        return root;
    }
}

字符串的排列

回溯法实现全排列。这里利用set实现去重的目的。

import java.util.ArrayList;
import java.util.*;

public class Solution {
    public ArrayList Permutation(String str) {
        ArrayList result = new ArrayList<>();
        if(str == null || str.length() == 0)
            return result;
        HashSet set = new HashSet<>();
        Permutation(set, str.toCharArray(), 0);
        result.addAll(set);
        Collections.sort(result);
        return result;
    }

    public void Permutation(HashSet set, char[] array, int k) {
        if(k > array.length - 1) {
            set.add(new String(array));
            return;
        }
        for(int i = k; i < array.length; i++) {
            swap(array, k, i);
            Permutation(set, array, k+1);
            swap(array, k, i);
        }
    }

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

数组中只出现一次的数字

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array == null || array.length <= 1) {
            num1[0] = 0;
            num2[0] = 0;
            return;
        }
        int diff = array[0];
        for(int i = 1; i < array.length; i++) 
            diff ^= array[i];

        String str = Integer.toBinaryString(diff);
        int index = str.length() - 1;
        for(; index >= 0; index--) {
            if(str.charAt(index) != '0')
                break;
        }
        index = str.length() - 1 - index;

        for(int i = 0; i < array.length; i++) {
            if(isBitZero(array[i], index))
                num1[0] ^= array[i];
            else
                num2[0] ^= array[i];
        }
    }

    public boolean isBitZero(int n, int index) {
        int assi = 1;
        for(int i = 0; i < index; i++)
            assi <<= 1;
        return ((assi & n) == 0) ? true : false;
    }
}

数组中重复的数字

这个解法时间复杂度O(N),不新建空间。很巧妙。

public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        if(numbers == null || numbers.length == 0 || length == 0)
            return false;
        for(int i = 0; i < length; i++) {
            int index = numbers[i];
            if(index < 0)
                index += length;
            if(numbers[index] < 0) {
                duplication[0] = index;
                return true;
            }
            else
                numbers[index] = numbers[index] - length;

        }
        return false;
    }
}

链表中环的入口结点

下面的解法很巧妙,遍历环的时候把上面的结点与这个结点解锁,这样最后一个没有next的就是环的入口节点。

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null || pHead.next == null)
            return null;
        while(pHead.next != null) {
            ListNode p = pHead.next;
            pHead.next = null;
            pHead = p;
        }
        return pHead;
    }
}

你可能感兴趣的:(读书,Java,算法)