剑指offer习题JAVA实现(三)

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

public class Solution {
    public ArrayList<String> Permutation(String str) {
       ArrayList<String> list=new ArrayList<String>();
       if(str==null||str.length()==0){
    	   return list;
       }
       char a[]=str.toCharArray();
       change(list,0,a);
       Collections.sort(list);
       return list;  
    }
    public void change(ArrayList<String> arr,int index,char[]s){
    	if(index==s.length-1){
    		arr.add(new String(s));
    	}
    	for(int i=index;i<s.length;i++){
    		if(i==index||s[index]!=s[i]){
    			swap(s,index,i);
    			change(arr,index+1,s);
    			swap(s,index,i);
    		}
    	}  	
    }
    public void swap(char[]t,int i,int j)
    {
       char c=t[i];
       t[i]=t[j];
       t[j]=c;
   }
}
2. 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        int len=array.length;
        int count[]=new int [1000];
        for(int i=0;i<len;i++){
        	count[array[i]]++;
        }
        int ssss = 0;
        int half=len/2;
        for(int i=0;i<count.length;i++){
        	if(count[i]>half){
        		ssss=i;
        	}
        }
        return ssss;
    }
}
3. 输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
      ArrayList<Integer> list=new ArrayList<Integer>();
    	ArrayList<Integer> list1=new ArrayList<Integer>();
        int len=input.length;
        if(k>len){
    		return list1;
    	}
    	for(int i=0;i<input.length;i++){
    		list.add(input[i]);
    	}
    	Collections.sort(list);
    	for(int i=0;i<k;i++){
    		list1.add(list.get(i));
    	}
    	return list1; 
    }
}
4. HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        ArrayList list=new ArrayList();        
        for(int i=0;i<array.length;i++){
        	int sum=0;
        	for(int j=i;j<array.length;j++){
        		sum +=array[j];
        		list.add(sum);
        	}
        }
        Collections.sort(list);
        return (Integer) list.get(list.size()-1);       
    }
}
5. 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
    	int count=0;
    	for(int i=0;i<=n;i++){
    		count +=getsum(i);
    	}
    	return count;
    }
    public int getsum(int i){
    	int sum=0;
    	while(i>0){
    		int p=i%10;
    		if(p==1) sum++;
    		i=i/10;
    	}
    	return sum;
    }
}
6. 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

public class Solution {
    public String PrintMinNumber(int [] numbers) {
		String a="";
		ArrayList<Integer> list=new ArrayList<Integer>();
		int n=numbers.length;
		for(int i=0;i<n;i++){
			list.add(numbers[i]);
		}
		Collections.sort(list,new Comparator<Integer>(){//重写sort方法,按照数字大小排列
		@Override
		public int compare(Integer a,Integer b){
			String aa=a+""+b;
			String bb=b+""+a;
			return aa.compareTo(bb);
		}
		});
		for(int j:list){
			a+=j;
		}
		return a;   
    }
} 
7. 把只包含素因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
public class Solution {
    public int GetUglyNumber_Solution(int index) {
       if(index<=0)
            return 0;
        int[] result = new int[index];
        int count = 0;
        int i2 = 0;
        int i3 = 0;
        int i5 = 0;
 
        result[0] = 1;
        int tmp = 0;
        while (count < index-1) {
            tmp = min(result[i2] * 2, min(result[i3] * 3, result[i5] * 5));
            if(tmp==result[i2] * 2) i2++;//三条if防止值是一样的,不要改成else的
            if(tmp==result[i3] * 3) i3++;
            if(tmp==result[i5]*5) i5++;
            result[++count]=tmp;
        }
        return result[index - 1];
    }
 
    private int min(int a, int b) {
        return (a > b) ? b : a;
    }
}
8. 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置。如果字符串为空,返回-1

public class Solution {
    public int FirstNotRepeatingChar(String str) {
       HashMap <Character,Integer>map=new HashMap<Character,Integer>();
		for(int i=0;i<str.length();i++){
			char ch=str.charAt(i);
			if(map.containsKey(ch)){
				int time=map.get(ch);
				time++;
				map.put(ch,time);
			}else{
				map.put(ch,1);
			}
		}
		for(int i=0;i<str.length();i++){
			char c=str.charAt(i);
			if(map.get(c)==1){
				return i;
			}
		}
		return -1;
    }
}
9. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007 
public class Solution {
    int result=0;
    public int InversePairs(int [] array) {
        int length=array.length;
        if(length<2) return 0;
        int tem[] = new int[length];
        merage(array,tem,0,length-1);
        return result;
    }
     public  void merage(int array[],int tem[],int left,int right){
        if(left<right){
            int middle=(left+right)/2;
            merage(array,tem,left,middle);
            merage(array,tem,middle+1,right);
            merageSort(array,tem,left,middle,right);
             
        }
    }
    public  void merageSort(int array[],int tem[],int left,int middle,int right){
        int i=left;
        int j=middle+1;
        int k=left;
        while(i<=middle&&j<=right){
            if(array[i]>array[j]){
                 
                result+=middle-i+1;
                result%=1000000007;
                tem[k++]=array[j++];
            }
            else tem[k++]=array[i++];
        }
        while(i<=middle)tem[k++]=array[i++];
        while(j<=right)tem[k++]=array[j++];
        for(int m=left;m<=right;m++) array[m]=tem[m];
    }
}
10. 输入两个链表,找出它们的第一个公共结点。
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
 		if (pHead1 == null||pHead2 == null) {
            return null;
        }
        int count1 = 0;
        ListNode p1 = pHead1;
        while (p1!=null){
            p1 = p1.next;
            count1++;
        }
        int count2 = 0;
        ListNode p2 = pHead2;
        while (p2!=null){
            p2 = p2.next;
            count2++;
        }
        int flag = count1 - count2;
        if (flag > 0){
            while (flag>0){
                pHead1 = pHead1.next;
                flag --;
            }
        while (pHead1!=pHead2){
            pHead1 = pHead1.next;
            pHead2 = pHead2.next;
        }
        return pHead1;
    }
        if (flag <= 0){
            while (flag<0){
                pHead2 = pHead2.next;
                flag ++;
            }
            while (pHead1 != pHead2){
                pHead2 = pHead2.next;
                pHead1 = pHead1.next;
            }
            return pHead1;
        }
        return null;
    }
}
11. 统计一个数字在排序数组中出现的次数。
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       int count=0;
       for(int i=0;i<array.length;i++){
    	   if(array[i]==k)
    		   count++;
       }
       return count;
    }
}
12. 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
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);
    }
}
13. 输入一棵二叉树,判断该二叉树是否是平衡二叉树。

平衡二叉树定义:平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
       if(root==null)
    		return true;
    	int left=getdeep(root.left);
    	int right=getdeep(root.right);
    	int flag=left-right;
    	if(flag>1||flag<-1)
    		return false;
    	return IsBalanced_Solution(root.left)&&IsBalanced_Solution(root.right);
    	
    }
    public int getdeep(TreeNode root){
    	if(root==null)
    		return 0;
    	else
    		return Math.max(getdeep(root.left), getdeep(root.right))+1;
    }
}
14. 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
       HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
        for(int i=0;i<array.length;i++){
        	Integer key=array[i];
        	Integer value=map.get(key);
        	if(value == null){
        		map.put(key, 1);
        	}else{
        		map.put(key,value+1);
        	}
        	
        }
        int index=0;
        for(int i=0;i<array.length;i++){
        	if(map.get(array[i])==1&&index==0){
        		num1[index]=array[i];
        		index++;
        	
        	}else if(map.get(array[i])==1&&index==1){
        		num2[index-1]=array[i];
        		break;
        	}      	
        }   
    }
}
15. 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck! 

扫描二维码关注公众号,回复: 863246 查看本文章
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
      ArrayList<ArrayList<Integer> > alist=new ArrayList<ArrayList<Integer> >();
		if(sum<2) 
			return alist;
		for(int i=1;i<=sum/2;i++){
			ArrayList<Integer> list=new ArrayList<Integer>();
			int count=0;
			for(int j=i;j<sum;j++){
				count+=j;
				list.add(j);
				if(count>sum){
					break;
				}else if(count==sum){
					alist.add(list);
					break;
				}
			}
	
		}
		return alist; 
    }
}
这部分主要是针对数组,字符串的操作,对于JAVA中的String类常用函数要必知必会,剩下的是二叉树的变形,平衡二叉树等需要额外学习。













猜你喜欢

转载自blog.csdn.net/qq_31278903/article/details/71315002