剑指offer题目汇总

3.搜索二维矩阵

复制代码
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix == null || matrix.length == 0){
return false;
}

boolean found = false;
if((matrix != null) && (matrix.length >0) && (matrix[0].length>0)){
int row = 0;
int column = matrix[0].length-1;
while((row < matrix.length)&&(column>=0)){
if(matrix[row][column]==target){
found = true;
break;
}else if(matrix[row][column]>target){
-- column;
}else{
++ row;
}
}
}
return found;
}
}
复制代码

4.替换空格

双指针方式

复制代码
public class Solution {
public String replaceSpace(StringBuffer str) {
int length = str.length();
if(str == null && length <= 0){
return str.toString();
}

int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(i<length){
++ originalLength;
if(str.charAt(i) == ' '){
++ numberOfBlank;
}
i++;
}

int newLength = originalLength + numberOfBlank*2;
str.setLength(newLength);

int indexOfOriginal = originalLength-1;
int indexOfNew = newLength-1;
while(indexOfOriginal >=0 && indexOfNew >0){
if(str.charAt(indexOfOriginal) == ' '){
str.setCharAt(indexOfNew--,'0');
str.setCharAt(indexOfNew--,'2');
str.setCharAt(indexOfNew--,'%');
--indexOfOriginal;
}else{
str.setCharAt(indexOfNew--,str.charAt(indexOfOriginal));

--indexOfOriginal;
}
}

return str.toString();
}
}
复制代码

stringbuffer方法

复制代码
public class Solution {
public String replaceSpace(StringBuffer str) {
for(int i=0;i<str.length();i++){
if(str.charAt(i) == ' '){
str.replace(i,i+1,"%20");
}
}

return str.toString();
}
}
复制代码

 

5.从尾到头打印链表

栈 先出后进

复制代码
 1 import java.util.ArrayList;
 2 import java.util.Stack;
 3 public class Solution {
 4 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
 5 Stack<Integer> stack=new Stack<Integer>();
 6 while(listNode!=null){
 7 stack.push(listNode.val);
 8 listNode=listNode.next; 
 9 }
10 
11 ArrayList<Integer> list=new ArrayList<Integer>();
12 while(!stack.isEmpty()){
13 list.add(stack.pop());
14 }
15 return list;
16 }
17 }
复制代码

 

递归法

复制代码
 1 import java.util.ArrayList;
 2 public class Solution {
 3 ArrayList<Integer> arrayList=new ArrayList<Integer>();
 4 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
 5 if(listNode!=null){
 6 this.printListFromTailToHead(listNode.next);
 7 arrayList.add(listNode.val);
 8 }
 9 return arrayList;
10 }
11 }
复制代码

6 重建二叉树

复制代码
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {

        if(startPre>endPre||startIn>endIn)
            return null;
        TreeNode root=new TreeNode(pre[startPre]);

        for(int i=startIn;i<=endIn;i++)
            if(in[i]==pre[startPre]){
                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
                break;
            }

        return root;
    }
}
复制代码

 

7 用两个栈实现队列

复制代码
import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        if(stack2.size()<=0){
            while(stack1.size()>0){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}
复制代码

8 旋转数组的最小数字

复制代码
import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array == null || array.length <=0){
            return 0;
        }
        int index1 = 0;
        int index2 = array.length-1;
        int indexMid = index1;
        while(array[index1] >= array[index2]){
            if(index2 - index1 == 1){
                indexMid = index2;
                break;
            }
            
            indexMid = (index1+index2)/2;
            
            if(array[indexMid] >= array[index1]){
                index1 = indexMid;
            }else if(array[indexMid] <= array[index2]){
                index2 = indexMid;
            }
        }
        return array[indexMid];
    }
}
复制代码

2.4.2 递归和循环

9 斐波那契数列

复制代码
public class Solution {
    public int Fibonacci(int n) {
        int preNum=1;
        int prePreNum=0;
        int result=0;
        if(n==0)
            return 0;
        if(n==1)
            return 1;
        for(int i=2;i<=n;i++){
            result=preNum+prePreNum;
            prePreNum=preNum;
            preNum=result;
        }
        return result;
    }
}
复制代码

青蛙跳台阶

复制代码
public class Solution {
    public int JumpFloor(int target) {
        if(target<2)
            return target;
        int f1=1;
        int f2=0;
        int f=0;
        for(int i=1;i<=target;++i)
            {
            f=f1+f2;
            f2=f1;
            f1=f;
        }
        return f;
    }
}
复制代码

变态跳台阶

复制代码
public class Solution {
    public int JumpFloorII(int target) {
        if (target <= 0) {
            return -1;
        } else if (target == 1) {
            return 1;
        } else {
            return 2 * JumpFloorII(target - 1);
        }
    }
}
复制代码

矩形覆盖

复制代码
public class Solution {
    public int RectCover(int target) {
        if (target <= 2){
            return target;
        }
        int pre1 = 2; // n 最后使用一块,剩下 n-1 块的写法
        int pre2 = 1; // n 最后使用两块,剩下 n-2 块的写法
        for (int i = 3; i <= target; i++){
            int cur = pre1 + pre2;
            pre2 = pre1;
            pre1 = cur;
        }
        return pre1; //相对于 n+1 块来说,第 n 种的方法
    }
}
复制代码

2.4.3 位运算

 10 二进制中1的个数

 

复制代码
public class Solution {
    public int NumberOf1(int n) {

        int count = 0;
        while(n!=0)
        {
            n = n&(n-1);
            count++;
        }
        return count;
    }
}
复制代码

 

11 数值的整数次方

循环

复制代码
public class Solution {
    public double Power(double base, int exponent) {
        if (exponent == 0) {
            return 1.0;
        }
        if (base - 0.0 == 0.00001 || base - 0.0 == -0.00001)  {
            if (exponent < 0) {
                throw new RuntimeException("除0异常"); 
            }else{
                return 0.0;
            }
        }
        int e = exponent > 0 ? exponent: -exponent;
        double result = 1;
        while (e != 0) {
            result = (e & 1) != 0 ? result * base : result;
            base *= base;
            e = e >> 1;
        }
        return exponent > 0 ? result : 1/result;
  }
}
复制代码

递归

复制代码
public class Solution {
    public double Power(double base, int exponent) {
        boolean flag = exponent < 0;
        if (flag) {
            exponent = -exponent;
        }
        double result = getPower(base, exponent);
        return flag ? 1 / result : result;
  }
   
    public static double getPower(double base, int exp) {
        if (exp == 0) {
            return 1;
        }
        if (exp == 1) {
            return base;
        }
        double ans = getPower(base, exp >> 1);
        ans *= ans;
        if ((exp & 1) == 1) {
            ans *= base;
        }
        return ans;
    }
}
复制代码

12 打印1到最大的n位数

13 在0(1)时间删除链表结点

14 调整数组顺序使奇数位于偶数前面

复制代码
public class Solution {
    public void reOrderArray(int [] array) {
        int length = array.length;
        if(length == 0){
            return;
        }
        int pBegin=0;
        int pEnd = length-1;
        
        while(pBegin < pEnd ){
            while(pBegin < pEnd && (array[pBegin] & 0x1) != 0){
                pBegin ++;
            }
            
            while(pBegin < pEnd && (array[pEnd] & 0x1) == 0){
                pEnd--;
            }
            
            if(pBegin < pEnd){
                int tmp = array[pBegin];
                array[pBegin] = array[pEnd];
                array[pEnd] = tmp;
            }
        }
    }
}
复制代码

拓展,牛客网多条件情况:并保证奇数和奇数,偶数和偶数之间的相对位置不变。

复制代码
public class Solution {
    public void reOrderArray(int [] array) {
        for (int i = 0; i < array.length;i++){
            for (int j = array.length - 1; j>i;j--)
            {
                if (array[j] % 2 == 1 && array[j - 1]%2 == 0) //前偶后奇交换
                {
                    int tmp = array[j];
                     array[j] = array[j-1];
                    array[j-1] = tmp;
                }
            }
        }
    }
}
复制代码

3.4 代码的鲁棒性

15 链表中倒数第k个结点、

复制代码
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head == null || k==0){
            return null;
        }
        
        ListNode pAhead = head;
        ListNode pBehind = null;
        
        for(int i=0;i<k-1;++i){
            if(pAhead.next != null){
                pAhead = pAhead.next;
            }else{
                return null;
            }
            
        }
        pBehind = head;
        while(pAhead.next != null){
            pAhead = pAhead.next;
            pBehind = pBehind.next;
        }
        return pBehind;
    }
}
复制代码

相关题目:

求链表中间结点

从链表头结点出发,一个指针走一步,一个指针走两步。

判断词汇表单向链表是否形成了环形结构。同上一个,如果走的快的指针追上了走得慢的指针,就是;如果走到链表末尾(next指向null),就不是。

应用--leetcode题目 141. 环形链表

复制代码
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null ){
            return false;
        }
        
        ListNode ahead = head.next;
        ListNode behind = head;
        
        while(ahead != behind){
            if(ahead.next == null || ahead.next.next == null){
                return false;
            }
            ahead = ahead.next.next;
            behind = behind.next;
        }
        return true;
    }
}
复制代码

16 反转链表

复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    ArrayList<Integer> arrayList=new ArrayList<Integer>();
    public ListNode reverseList(ListNode head) {
        ListNode reversedHead = null;
        ListNode node = head;
        ListNode prenode = null;
        while(node != null){
            ListNode next = node.next;
            if(next == null){
                reversedHead = node;
            }
            node.next = prenode;
            prenode = node;
            node = next;
        }
        return reversedHead;
    }
}
复制代码

17 合并两个排序的链表

复制代码
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null){
            return l2;
        }
        if(l2 == null){
            return l1;
        }

        ListNode mergeHead = null;

        if(l1.val >= l2.val){
            mergeHead = l2;
            mergeHead.next = mergeTwoLists(l1,l2.next);
        }else{
            mergeHead = l1;
            mergeHead.next = mergeTwoLists(l2,l1.next);
        }
        return mergeHead;
    }
}
复制代码

18 树的子结构

复制代码
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result = false;
        if(root1 != null && root2 != null){
            if(root1.val == root2.val){
                result = DoesTree1HasTree2(root1,root2);
            }
            if(!result){
                result = HasSubtree(root1.left,root2);
            }
            if(!result){
                result = HasSubtree(root1.right,root2);
            }
        }
         return result;
    }
    boolean DoesTree1HasTree2(TreeNode root1,TreeNode root2){
        if(root2 == null){
            return true;
        }
        if(root1 == null){
            return false;
        }
        if(root1.val!= root2.val){
            return false;
        }
        return DoesTree1HasTree2(root1.left,root2.left)&&
            DoesTree1HasTree2(root1.right,root2.right);
    }
}
复制代码

19 二叉树的镜像

递归实现

复制代码
public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null || 
           (root.left == null && root.right == null)){
            return;
        }
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        if(root.left != null){
            Mirror(root.left);
        }
        if(root.right != null){
            Mirror(root.right);
        }
    }
}
复制代码

循环实现

复制代码
import java.util.Stack;
public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null){
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node.left != null||node.right != null){
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
            }
            if(node.left!=null){
                stack.push(node.left);
            }
            if(node.right!=null){
                stack.push(node.right);
            }
        }
    }
}
复制代码

20 顺时针打印矩阵

复制代码
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> result = new ArrayList<Integer> ();
        if(matrix.length==0) return result;
        int row = matrix.length,col = matrix[0].length;
        if(col==0) return result;
        
         // 定义四个关键变量,表示左上和右下的打印范围
        int left = 0, top = 0, right = col - 1, bottom = row - 1;
        while(left <= right && top <= bottom){
            // left to right
            for (int i = left; i <= right; ++i)  result.add(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  result.add(matrix[i][right]);
            // right to left
            if (top != bottom)
            for (int i = right - 1; i >= left; --i)  result.add(matrix[bottom][i]);
            // bottom to top
            if (left != right)
            for (int i = bottom - 1; i > top; --i)  result.add(matrix[i][left]);
            left++;top++;right--;bottom--;
        }
        return result;    
    }
}
复制代码
复制代码
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        int row = matrix.size();
        int col = matrix[0].size();
        vector<int> res;
         
        // 输入的二维数组非法,返回空的数组
        if (row == 0 || col == 0)  return res;
         
        // 定义四个关键变量,表示左上和右下的打印范围
        int left = 0, top = 0, right = col - 1, bottom = row - 1;
        while (left <= right && top <= bottom)
        {
            // left to right
            for (int i = left; i <= right; ++i)  res.push_back(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  res.push_back(matrix[i][right]);
            // right to left
            if (top != bottom)
            for (int i = right - 1; i >= left; --i)  res.push_back(matrix[bottom][i]);
            // bottom to top
            if (left != right)
            for (int i = bottom - 1; i > top; --i)  res.push_back(matrix[i][left]);
            left++,top++,right--,bottom--;
        }
        return res;
    }
};
复制代码

21 包含min函数的栈

Stack实现

复制代码
import java.util.Stack;
public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    public void push(int node) {
        stack1.push(node);
        if(stack2.isEmpty() || node < stack2.peek()){
            stack2.push(node);
        }else{
            stack2.push(stack2.peek());
        }
    }
    
    public void pop() {
        assert(!stack1.isEmpty() && !stack2.isEmpty());
        stack1.pop();
        stack2.pop();
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        return stack2.peek();
    }
}
复制代码

ArrayList实现

复制代码
import java.util.ArrayList;
 
public class Solution {
 
    ArrayList<Integer> list = new ArrayList<Integer>();
     
    public void push(int node) {
        list.add(0,node);
    }
     
    public void pop() {
        list.get(0);
        list.remove(0);
    }
     
    public int top() {
        return list.get(0).intValue();
    }
 
    public int min() {
        int temp = top();
        for(int i=1;i<list.size();i++){
            if(temp>list.get(i).intValue()){
                temp = list.get(i).intValue();
            }
        }
        return temp;
    }
}
复制代码

22 栈的压入、弹出序列

 Stack实现

复制代码
import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      boolean bResult = false;
      int nLength = pushA.length;
      if(pushA != null && popA != null &&  nLength>0){
          int nextpush =0;
          int nextpop = 0;
          Stack<Integer> stackData = new Stack<Integer>();
          while(nextpop < nLength){
              while(stackData.empty() || stackData.peek() != popA[nextpop]){
                  if(nextpush == nLength){
                      break;
                  }
                  stackData.push(pushA[nextpush]);
                  nextpush++;
              }
              if(stackData.peek() != popA[nextpop]){
                  break;
              }
              stackData.pop();
              nextpop++;
          }
          if(stackData.empty() && nextpop == nLength){
              bResult = true;
          }
      }
        return bResult;
    }
}
复制代码

23 从上往下打印二叉树

按层打印,实际就是广度优先搜索 BFS, 借助一个队列就可以实现.

广度优先搜索 BFS:主要借助一个队列、一个布尔类型数组、邻接矩阵完成(判断一个点是否查看过,用于避免重复到达同一个点,造成死循环等),先将各点以及各点的关系存入邻接矩阵。

再从第一个点开始,将一个点存入队列,然后在邻接表中找到他的相邻点,存入队列,每次pop出队列头部并将其打印出来(文字有些抽象,实际过程很简单),整个过程有点像往水中投入石子水花散开。

复制代码
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        ArrayList<TreeNode> queue = new ArrayList<>();
        if (root == null) {
            return list;
        }
        queue.add(root);
        while (queue.size() != 0) {
            TreeNode temp = queue.remove(0);
            if (temp.left != null){
                queue.add(temp.left);
            }
            if (temp.right != null) {
                queue.add(temp.right);
            }
            list.add(temp.val);
        }
        return list;
    }
}
复制代码

扩展:

广度优先遍历一个有向图,同样可以基于队列实现。树是图的一种特殊退化形式,从上到下按层遍历二叉树,本质上就是广度优先遍历二叉树。

24 二叉搜索树的后序遍历序列

后序遍历:先遍历子结点,再遍历父结点。在后序遍历得到的序列中,最后一个数字是树的根结点。

 

复制代码
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence == null || sequence.length <= 0){
            return false;
        }
        int root = sequence[sequence.length-1];
        
        int[] sequenceleft = new int[sequence.length];
        int[] sequenceright = new int[sequence.length];
        
        //在二叉搜索树中左子树的结点小于结点
        int i=0;
        for(;i<sequence.length -1;++i){
            if(sequence[i] > root){
                break;
            }
            sequenceleft[i] = sequence[i];
        }
        
        //早二叉搜索树中右子树的结点大于根结点
        int j=i;
        int k=0;
        for(;j < sequence.length -1;++j){
            if(sequence[j] < root){
                return false;
            }
            k++;
            sequenceright[k] = sequence[j];
        }
        
        //判断左子树是不是二叉搜索树
        boolean left = true;
        if(i>0){
            left = VerifySquenceOfBST(sequenceleft);
        }
        
        boolean right = true;
        if(i<sequence.length-1){
            right = VerifySquenceOfBST(sequenceright);
        }
        return (left && right);        
    }
}
复制代码

 前中后序遍历

 

 

 

前、中、后指的是根节点的顺序。前序遍历有根节点开始。

前序遍历:ABCDEFGHK

中序遍历:BDCAEHGKF

后序遍历:DCBHKGFEA

中序排列思想:

25 二叉树中和为某一值的路径

复制代码
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        ArrayList<ArrayList<Integer>> paths=new ArrayList<ArrayList<Integer>>();
        if(root==null)return paths;
        find(paths,new ArrayList<Integer>(),root,target);
        return paths;
    }
    
    public void find(ArrayList<ArrayList<Integer>> paths,ArrayList<Integer> path,TreeNode root,int target){
            path.add(root.val);
            if(root.left==null&&root.right==null){
                if(target==root.val){
                    paths.add(path);
                }
                return;
            }
            ArrayList<Integer> path2=new ArrayList<>();
            path2.addAll(path);
            if(root.left!=null)find(paths,path,root.left,target-root.val);
            if(root.right!=null)find(paths,path2,root.right,target-root.val);
        }
}
复制代码
复制代码
import java.util.ArrayList;
import java.util.Stack;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        ArrayList<ArrayList<Integer>> pathList=
                new ArrayList<ArrayList<Integer>>();
        if(root==null)
            return pathList;
        Stack<Integer> stack=new Stack<Integer>();
        FindPath(root,target,stack,pathList );
        return pathList;
    }
    
    private void FindPath(TreeNode root, int target,
            Stack<Integer> path,
            ArrayList<ArrayList<Integer>> pathList) {
        if(root==null)
            return;
        if(root.left==null&&root.right==null){
            if(root.val==target){
                ArrayList<Integer> list=
                        new ArrayList<Integer>();
                for(int i:path){
                    list.add(new Integer(i));
                }
                list.add(new Integer(root.val));
                pathList.add(list);
            }
        }
        else{
            path.push(new Integer(root.val));
            FindPath(root.left, target-root.val, path, pathList);
            FindPath(root.right, target-root.val, path,  pathList);
            path.pop();
        }
    }
}
复制代码

26 复杂链表的复制

分治法,通常分治法的思路都可以用递归实现

在复杂链表的结点中,除了有指向下一个结点的指针,还有指向任意结点的指针。、

复制代码
/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        CloneNodes(pHead);
        ConnectSiblingNodes(pHead);
        return ReconnectNodes(pHead);
    }
    
    void CloneNodes(RandomListNode pHead){
        RandomListNode pNode = pHead;
        while(pNode != null){
            RandomListNode pCloned = new RandomListNode(pNode.label);
            pCloned.next = pNode.next;
            pCloned.random = null;
            
            pNode.next = pCloned;
            pNode = pCloned.next;
        }
    }
    
    void ConnectSiblingNodes(RandomListNode pHead){
        RandomListNode pNode = pHead;
        while(pNode!= null){
            RandomListNode pCloned = pNode.next;
            if(pNode.random != null){
                pCloned.random = pNode.random.next;
            }
            pNode = pCloned.next;
            
        }
    }
    
    RandomListNode ReconnectNodes(RandomListNode pHead){
        RandomListNode pNode = pHead;
        RandomListNode pClonedHead = null;
        RandomListNode pClonedNode = null;
        
        if(pNode != null){
            pClonedNode = pNode.next;
            pClonedHead = pClonedNode;
            pNode.next = pClonedNode.next;
            pNode = pNode.next;
        }
        
        while(pNode != null){
            pClonedNode.next = pNode.next;
            pClonedNode = pClonedNode.next;
            pNode.next = pClonedNode.next;
            pNode = pNode.next;
        }
        return pClonedHead;
    }
}
复制代码

 

27 二叉搜索树与双向链表

二叉搜索树:左子结点的值小于父结点的值,右子节点的值大于父结点的值。

直接递归

复制代码
public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null) return pRootOfTree;
        pRootOfTree = ConvertNode(pRootOfTree);
        while(pRootOfTree.left!= null) pRootOfTree = pRootOfTree.left;
        return pRootOfTree;
    }
    
    TreeNode ConvertNode(TreeNode root)
    {
        if(root == null) return root;
        if(root.left != null)
        {
            TreeNode left = ConvertNode(root.left);
            while(left.right!= null) left = left.right;
            left.right = root;
            root.left = left;
        }
         
        if(root.right != null)
        {
            TreeNode right = ConvertNode(root.right);
            while(right.left!= null) right = right.left;
            right.left = root;
            root.right = right;
        }
        return root;
    }
}
复制代码

 

此解法暂时未通过

复制代码
public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        TreeNode pLastNodeInList = null;
        ConvertNode(pRootOfTree, pLastNodeInList);
        
        //pLastNodeInList双向链表尾结点
        //需要返回头结点
        TreeNode pHeadOfList = pLastNodeInList;
            while(pHeadOfList != null && pHeadOfList.left != null){
                pHeadOfList = pHeadOfList.left;
            }
        return pHeadOfList;
    }
    
    void ConvertNode(TreeNode pNode, TreeNode pLastNodeInList){
        if(pNode == null){
            return;
        }
        TreeNode pCurrent = pNode;
        if(pCurrent.left != null){
           ConvertNode(pCurrent.left, pLastNodeInList);
        }
        
        pCurrent.left = pLastNodeInList;
        if(pLastNodeInList != null){
            pLastNodeInList.right = pCurrent;
        }
        
        pLastNodeInList = pCurrent;
        
        if(pCurrent.right != null){
            ConvertNode(pCurrent.right,pLastNodeInList);
        }
    }
}
复制代码

 

28 字符串的排列

 解法一:递归

复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> list = new ArrayList<String>();
        if(str!=null && str.length()>0){
            PermutationHelper(str.toCharArray(),0,list);
            Collections.sort(list);
        }
        return list;
    }

    private void PermutationHelper(char[] chars,int i,ArrayList<String> list){
        if(i == chars.length-1){
            list.add(String.valueOf(chars));
        }else{
            Set<Character> charSet = new HashSet<Character>();
            for(int j=i;j<chars.length;++j){
                if(j==i || !charSet.contains(chars[j])){
                    charSet.add(chars[j]);
                    swap(chars,i,j);
                    PermutationHelper(chars,i+1,list);
                    swap(chars,j,i);
                }
            }
        }
    }
 
    private void swap(char[] cs,int i,int j){
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }
}
复制代码

解法二:字典序排列算法

复制代码
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> list = new ArrayList<String>();
        if(str==null || str.length()==0){
            return list;
        }
        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        list.add(String.valueOf(chars));
        int len = chars.length;
        while(true){
            int lIndex = len-1;
            int rIndex;
            while(lIndex>=1 && chars[lIndex-1]>=chars[lIndex]){
                lIndex--;
            }
            if(lIndex == 0)
                break;
            rIndex = lIndex;
            while(rIndex<len && chars[rIndex]>chars[lIndex-1]){
                rIndex++;
            }
            swap(chars,lIndex-1,rIndex-1);
            reverse(chars,lIndex);
 
            list.add(String.valueOf(chars));
        }
 
        return list;
    }
    
    private void reverse(char[] chars,int k){
        if(chars==null || chars.length<=k)
            return;
        int len = chars.length;
        for(int i=0;i<(len-k)/2;i++){
            int m = k+i;
            int n = len-1-i;
            if(m<=n){
                swap(chars,m,n);
            }
        }
 
    }
 
    private void swap(char[] cs,int i,int j){
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }
}
复制代码

29 数组中出现次数超过一半的数字

方法1:

复制代码
import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        Arrays.sort(array);
        int count=0;
         
        for(int i=0;i<array.length;i++){
            if(array[i]==array[array.length/2]){
                count++;
            }
        }
        if(count>array.length/2){
            return array[array.length/2];
        }else{
            return 0;
        }
    }
}
复制代码

方法2:HashMap

复制代码
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
         
        for(int i=0;i<array.length;i++){
             
            if(!map.containsKey(array[i])){
               map.put(array[i],1);
            }else{
                int count = map.get(array[i]);
                map.put(array[i],++count);
            }
        }
        Iterator iter = map.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry entry = (Map.Entry)iter.next();
            Integer key =(Integer)entry.getKey();
            Integer val = (Integer)entry.getValue();
            if(val>array.length/2){
                return key;
            }
        }
        return 0;
    }
}
复制代码

方法3:快排思想--未通过

复制代码
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
       if(array.length<=0)
                return 0;

        int start = 0;
        int length = array.length;
        int end  = length-1;
        int middle = length>>1;

        int index = Partition(array,start,end);

        while(index!=middle){

            if(index>middle){
                index = Partition(array,start,index-1);
            }
            else{
                index = Partition(array,index+1,end);
            }
        }
        int result = array[middle];

        int times = 0;
        for(int i=0;i<length;++i){
            if(array[i] == result)
                times++;
        }
        if(times*2<length){
            System.out.println(times);
            return 0;
        }else{
            return result;
        }
    }
    
    public int Partition(int[] array,int start,int end){
        int flag = (array[start]+array[end])/2;

        while(start<end){
            while(array[end]>flag){
                end--;
            }
            swap(array,start,end);
            while(array[start]<=flag){
                start++;
            }
            swap(array,start,end);
        }
        return start;
    }
    public void swap(int[] array,int num1,int num2){
        int temp =array[num1];
        array[num1] =array[num2];
        array[num2] =temp;
    }
}
复制代码

 

30 最小的K个数

解法一:冒泡排序

复制代码
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> al = new ArrayList<Integer>();
        if (k > input.length) {
            return al;
        }
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < input.length - i - 1; j++) {
                if (input[j] < input[j + 1]) {
                    int temp = input[j];
                    input[j] = input[j + 1];
                    input[j + 1] = temp;
                }
            }
            al.add(input[input.length - i - 1]);
        }
        return al;
    }
}
复制代码

解法2:利用快速排序中的获取分割(中轴)点位置函数getPartitiion--用例未通过

复制代码
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<Integer>();       
        if(input==null || k>input.length || k<=0) return result;
         
        int start = 0;
        int end = input.length-1;
        int index = getPartition(input,start,end);
         
        while(index != (k-1))
        {
            if(index > (k-1))
            {
                end = index - 1;
                index = getPartition(input,start,end);
            }
            else
            {
                start = index + 1;
                index = getPartition(input,start,end);
            }
        }
         
        for(int i=0;i<k;++i)
        {
            result.add(input[i]);
        }
         
        return result;
    }
    public void swap(int fir,int sec)
    {
        int temp = fir;
        fir = sec;
        sec = temp;
    }
     
    public int getPartition(int [] input,int start,int end)
    {
        if(input==null || start>end) return -1;
        int temp = input[end];
        int j = start - 1;
        for(int i=start;i<end;++i)
        {
            if(input[i]<=temp)
            {
                ++j;
                if(i!=j) swap(input[i],input[j]);                   
            }
        }
        swap(input[j+1],input[end]);
        return (j+1);
    }
}
复制代码

 

31 连续子数组的最大和

解法1:分析数组规律

复制代码
public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        int len = array.length;
        if(array==null || len<0){
            return 0;
        }
        int nCurSum = 0;
        int nGreatestSum = 0x80000000;
        for(int i=0; i<len;i++){
            if(nCurSum <= 0){
                nCurSum = array[i];
            }else{
                nCurSum += array[i];
            }
            if(nCurSum > nGreatestSum){
                nGreatestSum = nCurSum;
            }
        }
        return nGreatestSum;
    }
}
复制代码

解法2:动态规划思想,代码一致

32 从1到n整数中1出现的次数 

 

复制代码
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int number = 0;
        for(int i=0;i<=n;i++){
            number += numberOf1(i);
        }
        return number;
    }
    public int numberOf1(int n){
        int number = 0;
        while(n>0){
            if(n%10 == 1){
                number ++;
            }
            n = n/10;
        }
        return number;
    }
}
复制代码

 

33 把数组排成最小的数

 

复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        int n;
        String s="";
        ArrayList<Integer> list= new ArrayList<Integer>();
        n=numbers.length;
        for(int i=0;i<n;i++){
            list.add(numbers[i]);
        }

        Collections.sort(list, new Comparator<Integer>(){
  
            public int compare(Integer str1,Integer str2){
                String s1=str1+""+str2;
                String s2=str2+""+str1;
                return s1.compareTo(s2);
            }
        });

        for(int j:list){
            s+=j;
        }
        return s;
    }
}
复制代码

 

复制代码
import java.util.ArrayList;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        String str = "";
        for (int i=0; i<numbers.length; i++){
            for (int j=i+1; j<numbers.length; j++){
                int a = Integer.valueOf(numbers[i]+""+numbers[j]);
                int b = Integer.valueOf(numbers[j]+""+numbers[i]);
                if (a > b){
                    int t = numbers[i];
                    numbers[i] = numbers[j];
                    numbers[j] = t;
                }
                 
            }
        }
        for (int i = 0; i < numbers.length; i++) {
            str += String.valueOf(numbers[i]);
        }
        return str;
    }
}
复制代码

 

34 丑数

解法一:暴力破解 超时

复制代码
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index <= 0){
            return 0;
        }
        int number = 0;
        int uglyFound = 0;
        while(uglyFound < index){
            ++number;
            if(IsUgly(number)){
                ++uglyFound;
            }
        }
        return number;        
    }
    boolean IsUgly(int number){
        while(number % 2 == 0){
            number /= 2;
        }
        while(number % 3 == 0){
            number /= 3;
        }
        while(number % 5 == 0){
            number /= 5;
        }
        return (number==1)?true:false;
    }
}
复制代码

方法二:创建数组保存已找到的丑数,用空间换时间

复制代码
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index <=0){
            return 0;
        }

        int[] uglyNums = new int[index];
        uglyNums[0]=1;
        
        int nextUglyIndex = 1;
        int mul2 = 0;
        int mul3 = 0;
        int mul5 = 0;
        
        while(nextUglyIndex < index){
            int min = Min(uglyNums[mul2]*2, uglyNums[mul3]*3, uglyNums[mul5]*5);
            uglyNums[nextUglyIndex] = min;
            
            while(uglyNums[mul2]*2 <= uglyNums[nextUglyIndex]){
                ++mul2;
            }
            while(uglyNums[mul3]*3 <= uglyNums[nextUglyIndex]){
                ++mul3;
            }
            while(uglyNums[mul5]*5 <= uglyNums[nextUglyIndex]){
                ++mul5;
            }
            ++nextUglyIndex;
        }
        int ugly = uglyNums[nextUglyIndex - 1];
        return ugly;            
    }
    
    int Min(int num1, int num2, int num3){
        int min = (num1 <= num2)?num1:num2;
        min = (min <= num3)?min:num3;
        return min;
    }
}
复制代码

 

35 第一个只出现一次的字符

方法1:哈希表 ASCII码

复制代码
public class Solution {
    public int FirstNotRepeatingChar(String str) {
    int[] words = new int[58];
    for(int i = 0;i<str.length();i++){
        words[((int)str.charAt(i))-65] += 1;
    }
    for(int i=0;i<str.length();i++){
        if(words[((int)str.charAt(i))-65]==1)
            return i;
    }
    return -1;
    }
}
复制代码

方法2:字符串函数  第一次和最后一次出现的位置相同

复制代码
public class Solution {
    public int FirstNotRepeatingChar(String str) {
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (str.indexOf(ch) == str.lastIndexOf(ch))
                return i;
        }
        return -1;
    }
}
复制代码

 

***相似题目*** 统计多个字符是不是在字符串出现过或者次数

删除第一个字符串中在第二个字符串中出现的字符

删除字符串中所有重复出现的字符

变位词

36 数组中的逆序对

方法1:归并排序 按书上代码没有通过用例

复制代码
public class Solution {
    public int InversePairs(int [] array) {
        if(array == null || array.length <0){
            return 0;
        }
        int len = array.length;
        int[] copy = new int[len];
        for(int i=0;i<len;++i){
            copy[i] = array[i];
        }
        int count  = InversePairsCore(array,copy,0,len-1);
        
        return count;
    }
    
    int InversePairsCore(int[] array, int[] copy, int start, int end){
        if(start == end){
            copy[start] = array[start];
            return 0;
        }
        int len = (end - start)/2;
        
        int left = InversePairsCore(copy, array, start, start + len);
        int right = InversePairsCore(copy, array, start + len+1,end);
        
        int i =start +len;
        int j=end;
        int indexCopy = end;
        int count = 0;
        while(i>= start && j >= start + len+ 1){
            if(array[i] > array[j]){
                copy[indexCopy--] = array[i--];
                count += j-start-len;
            }else{
                copy[indexCopy--] = array[j--];
            }
        }
        for(;i>=start;--i){
            copy[indexCopy--] = array[i];
        }
        for(;j>= start + len +1;--j){
            copy[indexCopy] = array[j];
        }
        return left+right+count;
    }
}
复制代码

 

37 两个链表的第一个公共结点

 

复制代码
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        int len1 = GetListLen(pHead1);
        int len2 = GetListLen(pHead2);
        int lendif = len1-len2;
        
        ListNode headLong = pHead1;
        ListNode headShort = pHead2;
        if(len2>len1){
            headLong = pHead1;
            headShort = pHead2;
            lendif = len2-len1;
        }
        
        for(int i=0;i<lendif;++i){
            headLong = headLong.next;
        }
        while(headLong != null && headShort != null && headLong != headShort){
            headLong = headLong.next;
            headShort = headShort.next;
        }
        ListNode firstCommNode = headLong;
        return firstCommNode;
    }
    int GetListLen(ListNode pHead){
        int len = 0;
        ListNode pNode = pHead;
        while(pNode != null){
            ++ len;
            pNode = pNode.next;
        }
        return len;
    }
}
复制代码

38 数字在排序数组中出现的次数

方法1:二分法:

复制代码
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       int number = 0;
        int len = array.length;
        if(array != null && len >0){
            int first = GetFirstK(array, len,k, 0,len-1);
            int last = GetLastK(array, len,k,0,len-1);
            
            if(first > -1 && last > -1){
                number = last-first+1;
            }
        }
        return number;
    }
    
    int GetFirstK(int[] array, int length, int k, int start, int end){
        if(start > end){
            return -1;
        }
        int midIndex = (start + end)/2;
        int midData = array[midIndex];
        
        if(midData == k){
            if((midIndex > 0 && array[midIndex -1] != k) || midIndex==0){
                return midIndex;
            }else{
                end = midIndex -1;
            }
        }else if(midData > k){
            end = midIndex - 1;
        }else{
            start = midIndex +1;
        }
        return GetFirstK(array, length, k, start, end);
    }
    
        int GetLastK(int[] array, int length, int k, int start, int end){
        if(start > end){
            return -1;
        }
        int midIndex = (start + end)/2;
        int midData = array[midIndex];
        
        if(midData == k){
            if((midIndex <length-1 && array[midIndex + 1] != k) || midIndex==length-1){
                return midIndex;
            }else{
                start = midIndex + 1;
            }
        }else if(midData < k){
            start = midIndex +1;
        }else{
            end = midIndex - 1;
        }
        return GetLastK(array, length, k, start, end);
    }
}
复制代码

 

39 二叉树的深度

复制代码
public class Solution {
    public int TreeDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        int left = TreeDepth(root.left);
        int right = TreeDepth(root.right);
        
        return (left>right)?(left+1):(right+1);
    }
}
复制代码

 

****拓展:平衡二叉树

二叉树中任意结点的左右子树的深度相差不超过1就是平衡二叉树。

解法1:

复制代码
public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root == null){
            return true;
        }
        int left = TreeDepth(root.left);
        int right = TreeDepth(root.right);
        int diff = left-right;
        if(diff > 1 || diff < -1){
            return false;
        }
        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
    }
    
        public int TreeDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        int left = TreeDepth(root.left);
        int right = TreeDepth(root.right);
        
        return (left>right)?(left+1):(right+1);
    }
}
复制代码

解法2:每个结点遍历一次 ---未通过所有用例

复制代码
public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        int depth = 0;
        return IsBalanced_Solution(root, depth);
    }
    
    public boolean IsBalanced_Solution(TreeNode root, int depth) {
        if(root == null){
            depth = 0;
            return true;
        }
        int left=depth;
        int right=depth;
        if(IsBalanced_Solution(root.left, left) && IsBalanced_Solution(root.right, right)){
            int diff = left - right;
            if(diff <= 1 && diff >= -1){
                depth = 1+(left>right ? left:right);
                return true;
            }
        }
        return false;
    }
}
复制代码

 

40 数组中只出现一次的数字

--未通过

复制代码
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
       if(array.length < 2){
           return;
       }
        if(array.length == 2){
            num1[0] = array[0];
            num2[0] = array[1];
            return;
        }
        
        int resultExclusiveOR = array[0];
        for(int i=0; i<array.length; ++i){
            resultExclusiveOR ^= array[i];
        }
        int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
        
        for(int j=0; j<array.length;++j){
            if(IsBit1(array[j],indexOf1)){
                num1[j] ^= array[j];
            }else{
                num2[j] ^= array[j];
            }
        }
    }
    
    int FindFirstBitIs1(int num){
        int indexBit = 0;
        while((num &1)==0 && indexBit < 32){
            num = num >>1;
            indexBit++ ;
        }
        return indexBit;
    }
    
    boolean IsBit1(int num, int indexBit){
        num = num >> indexBit;
        return (num&1) == 1;
    }
}
复制代码

 

41 和为s的两个数字 VS 和为s的连续正数序列

42 反转单词顺序 VS 左旋转字符串

43 n个骰子的点数

44 扑克牌的顺子

45 圆圈中最后剩下的数字

46 求1+2+...+n

47 不用加减乘除做加法

48 不能被继承的类

49 把字符串转换成整数

50 书中两个结点的最低公共祖先

 

posted @ 2020-05-26 21:25  小仙女学编程  阅读(177)  评论(0编辑  收藏  举报