剑指OFFER 算法练习

1.在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。

    请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

public class Solution {
    public boolean Find(int target, int [][] array) {
        int m = array.length;
        int n = array[0].length;
        
        int i = m-1;
        int j = 0;
        while(i >= 0 && j < n) {
            if(array[i][j] == target) 
                return true;
            else if(array[i][j] > target)
                i--;
            else
                j++;
        }
        return false;
    }
}

2.请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

public class Solution {
    public String replaceSpace(StringBuffer str) {
	 StringBuffer sb = new StringBuffer();
	 String re = new String("%20");
        String s = str.toString();
	 char[] c = s.toCharArray();
	 for(int i=0;i<c.length;i++) {
		if(c[i] == ' ')
			sb.append(re);
		else
			sb.append(c[i]);
	}
	return sb.toString();
    }
}

3.从尾到头打印链表的值

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
import java.util.Collections;

public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> al = new ArrayList<Integer> ();
        ListNode ln = listNode;
        while(ln != null) {
            al.add(ln.val);
            ln = ln.next;
        }
        Collections.reverse(al);
        return al;
    }
}

4.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

   例如输入前序遍历序列{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) {
        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);
            }
                 
        return root;
    }
}


5.两个栈模拟一个队列

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
    	
    	if(stack1.size() == stack1.capacity()) {
    		if(stack2.isEmpty()) {
    			while(!stack1.isEmpty())
    				stack2.push(stack1.pop());
    			stack1.push(node);
    		}
    		else 
			System.out.println("the quenue is \'full!\' ");	
    	}
    	else 
			stack1.push(node);
        
    }
    
    public int pop() {
    	if(stack2.isEmpty()) {
    		if(stack1.isEmpty())
    			System.out.println("the quenue is \'empty!\' ");
    		else {
    			while(!stack1.isEmpty())
    				stack2.push(stack1.pop());
    		}
    	}
    	return stack2.pop();
    }
}

6. 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
    	
    	if(array.length == 0)
    		return 0;
//    	int min = Integer.MAX_VALUE;
//    	for(int t : array) {
//    		if(min > t)
//    			min = t;
//    	}
//    	return min;

    	int low = 0 , high = array.length-1;
    	int mid = (low + high) / 2;
    	
    	while(true) {
    		if(array[low] <= array[mid])
    			low = mid;
    		else 
    			high = mid;
    		
    		if(low + 1 == high)
    			return array[high];
    		else 
    			mid = (low + high) / 2;
    	}
    }
}

7. 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。 n<=39

public class Solution {
    public int Fibonacci(int n) {
    	if(n>39)
    		System.exit(0);;
    	if( n==1 || n==0)
    		return n;
    	else 
			return Fibonacci(n-1) + Fibonacci(n-2);
    }
}


8.一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
public class Solution {
    
    public int JumpFloor(int target) {
    	/*递归*/
//    	if( target == 1 || target == 2 ) 
//    		return target;
//    	else 
//			return JumpFloor(target-1) + JumpFloor(target-2);

    	
    	/*动态规划*/
    	if( target > 2 ) {
    		int Restore[] = new int[target+1];
        	Restore[1] = 1;
        	Restore[2] = 2;
        	int n = 3;
			int tmp = 0;
			while( n <= target ) {
				tmp = Restore[n-1]+Restore[n-2];
				Restore[n++] = tmp;
			}
			return Restore[target];
    	}
    	else 
			return target;
    }
}

9.一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

public class Solution {

    public int JumpFloorII(int target) {
    	
    	/*递归*/
    	if( target == 1 || target == 2 ) 
    		return target;
    	else {
    		int result = 0;
    		for(int i=1; i<target; i++)
    			result += JumpFloorII(target - i);
    		return result + 1;
    	}
    }
    		
    	/*动态规划*/
//    	if( target > 2 ) {
//    		int Restore[] = new int[target+1];
//        	Restore[1] = 1;
//        	Restore[2] = 2;
//        	int n = 3;
//			int tmp = 0;
//			while( n <= target ) {
//				for(int i=1; i<n; i++)
//					tmp += Restore[n-i];
//				Restore[n++] = tmp+1;
//				tmp = 0;
//			}
//			return Restore[target];
//        	
//    	}
//    	else 
//			return target;
//    }
}

10.我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

public class Solution {
    public int RectCover(int target) {
    	int result[] = new int[target+1];
    	if(target == 1 || target == 2 || target == 0)
    		return target;
    	result[0] = 0;
    	result[1] = 1;
    	result[2] = 2;
    	for(int i=3; i<=target; i++) 
    		result[i] = result[i-1] + result[i-2];
    	return result[target];
    }
}

11.输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

public class Solution { 
      public int NumberOf1(int n) { 
          int count = 0; 
          while(n!= 0){ 
              count++; 
              n = n & (n - 1);
           } 
          return count; 
      } 
  }

/*
如果一个整数不为0,那么这个整数至少有一位是1。
如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,
原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
  
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。
减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.
我们发现减1的结果是把最右边的一个1开始的所有位都取反了。
这个时候如果我们再把原来的整数和减去1之后的结果做与运算,
从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.
也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.
那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

*/

public class Solution {
    public int NumberOf1(int n) {
    	int count = 0;
    	if (n<0) {
    		n = n &0x7FFFFFFF;
    		count++;
    	}
    	while(n != 0) {
    		count += n & 1;
    		n = n >> 1;
    	}
    	return count;
    }
}
/*
首先判断n是不是负数,当n为负数的时候,直接用后面的while循环会导致死循环,因为负数
向左移位的话最高位补1 ! 因此需要一点点特殊操作,可以将最高位的符号位1变成0,也就
是n & 0x7FFFFFFF,这样就把负数转化成正数了,唯一差别就是最高位由1变成0,因为少了
一个1,所以count加1。之后再按照while循环里处理正数的方法来操作就可以啦!
*/


12.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

public class Solution {
    public void reOrderArray(int [] array) {
    	ArrayList<Integer> Odd = new ArrayList<Integer>();
    	ArrayList<Integer> Even = new ArrayList<Integer>();
    	for(int tmp : array) {
    		if( tmp % 2 == 0)
    			Even.add(tmp);
    		else
    			Odd.add(tmp);
    	}
    	int i = 0;
    	Iterator<Integer> it1 = Odd.iterator();
    	Iterator<Integer> it2 = Even.iterator();
    	while(it1.hasNext()) 
    		array[i++] = it1.next();
    	while(it2.hasNext()) 
    		array[i++] = it2.next();    		
        for(int d : array) 
        	System.out.print(d+" ");
    }
}

13.输入一个链表,输出该链表中倒数第k个结点。

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

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

import java.util.ArrayList;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {

    	ArrayList<ListNode> array = new ArrayList<ListNode>();
    	ListNode tmp = head;
    	while(tmp != null) {
    		array.add(tmp);
    		tmp = tmp.next;
    	}
    	int i = 0;
    	ListNode result = null ;
    	if(array.size() < k || k < 1)
    		return null;
        result = array.get(array.size()-k);
    	return result;
    }
}


14. 输入一个链表,反转链表后,输出链表的所有元素。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.Stack;
public class Solution {
	public ListNode ReverseList(ListNode head) {
		if(head == null|| head.next == null)
			return head;
		
		ListNode pre = null;
		ListNode current = head;
		ListNode next = head.next;
		
		while( next != null ) {
			current.next = pre;
			pre = current;
			current = next;
			next = current.next;
		}
		current.next = pre;
		return current;
	}
}

//利用栈实现
	public ListNode ReverseList(ListNode head) {
		
		Stack<ListNode> stack = new Stack<ListNode>();
		
		if(head == null|| head.next == null)
			return head;
		
		ListNode tmp = head;
		
		while(tmp != null) 
			stack.push(tmp);
		
		ListNode nhead = stack.pop();
		tmp = nhead.next;
		while(!stack.isEmpty()) { 
			tmp = stack.pop();
			tmp = tmp.next;
		}
		tmp.next = null;
		return nhead;
	}

//利用头插法实现
    public ListNode ReverseList(ListNode head) {
    	
    	ListNode nhead = null,tmp = head;
    	int i=0;
    	while(tmp != null) {
    		i++;
    		nhead = tmp;
    		tmp = tmp.next;
    	}
    	
    	if(i == 0)
    		return null;
    	else if(i == 1)
    		return head;
    	
    	tmp = head;
    	ListNode newtmp = nhead.next;
    	for(int j=0;j<i-1;j++) {
    		newtmp = tmp;
    		newtmp = newtmp.next;
    		tmp = tmp.next;
    	}
    	return nhead;
    }

15.输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
	public ListNode Merge(ListNode list1,ListNode list2) {
		
		ListNode data = null;
        
		if(list1 == null ) 
			return list2;
		if(list2 == null)
			return list1;
		if(list1.val < list2.val) {
			data = list1;
			data.next = Merge(list1.next,list2);
		}
		else {
			data = list2;
			data.next = Merge(list1,list2.next);
		}
		return data;
	}
}
//非递归
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
 public ListNode Merge(ListNode list1,ListNode list2) {
    	
    	ListNode result = null;
    	ListNode current = null;
    	
    	ListNode l1 = list1;
    	ListNode l2 = list2;

    	if(l1 == null)
    		return l2;
    	if(l2 == null)
    		return l1;
    	
    	if(l1.val < l2.val) {
    		result = l1;
    		current = result;
    		l1 = l1.next;
		}
    	else {
    		result = l2;
    		current = result;
    		l2 = l2.next;
    	}
    		
    	
    	while(l1 != null && l2 != null) {
    		if(l1.val < l2.val) {
    			current.next = l1;
    			current = current.next;
    			l1 = l1.next;
    		}
    		else {
    			current.next = l2;
    			current = current.next;
    			l2 = l2.next;
    		}
    	}
     
    	if( l1 == null )
    		current.next = l2;
    	if( l2 == null )
    		current.next = l1;
    	
        return result;
    }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值