剑指offer(31-40)

31.求出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=1;i<=n;i++){   
            int tmp=i;
            while(tmp!=0){
                if(tmp%10==1)
                	count++;
                
                tmp=tmp/10;
            }
        }
        
        return count;
    }
}

32.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
    思路:
先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来。关键就是制定排序规则。
  * 排序规则如下:
  * 若ab > ba 则 a > b,
  * 若ab < ba 则 a < b,
  * 若ab = ba 则 a = b;
  * 解释说明:
  * 比如  "3" <  "31" 但是  "331" >  "313" ,所以要将二者拼接起来进行比较
代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class Solution {
    public String PrintMinNumber(int [] numbers) {

        if(numbers == null || numbers.length == 0) 
            return "";
                  
        int len=numbers.length;        
        String[] s=new String[len];
        StringBuilder sb=new StringBuilder();
        
        for(int i=0;i<len;i++){
            s[i]=String.valueOf(numbers[i]);
        }
        
        //重新定义比较规则
         Arrays.sort(s,new Comparator<String>(){
            @Override
            public int compare(String s1, String s2) {
          	String c1=s1+s2;
                String c2=s2+s1;
                return c1.compareTo(c2);
            }
        });
        
        for(int i=0;i<len;i++){
            sb.append(s[i]);
        }
        
        return sb.toString();
    }
}

33.把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
    思路: 要注意,后面的丑数是有前一个丑数乘以2,3,5中的一个得来。因此可以用动态规划去解
代码:
public class Solution {
    public int GetUglyNumber_Solution(int index) {
  
        if(index==0) 	return 0;    
        if(index==1)	return 1;
        
        int[] k=new int[index];
        k[0]=1;
        int t2=0;int t3=0;int t5=0;
        
        for(int i=1;i<index;i++){
            k[i]=Math.min(k[t2]*2,Math.min(k[t3]*3,k[t5]*5));
            if(k[i]==k[t2]*2) t2++;
            if(k[i]==k[t3]*3) t3++;
            if(k[i]==k[t5]*5) t5++;
        }
        
        return k[index-1];
    }
}

34.在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置
    思路:使用HashMap,第一遍存储,第二遍查询
代码:
import java.util.HashMap;

public class Solution {
    public int FirstNotRepeatingChar(String str) {
       
        if(str==null||str.length()==0)
            return -1;
        
        HashMap<Character,Integer> map=new HashMap<Character,Integer>();
        char[] c=str.toCharArray();
        int r=-1;
        
        for(int i=0;i<c.length;i++){
            if(map.get(c[i])==null){
                
                map.put(c[i],1);
            }else{
                
                map.put(c[i],map.get(c[i])+1);
            }
        }
        
        
        for(int i=0;i<c.length;i++){
            if(map.get(c[i])==1){
                r=i;
                break;
            }
            
        }
        
        return r;
    }
}

35. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007 
输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5



输入例子:
1,2,3,4,5,6,7,0

输出例子:
7
    思路:

36.输入两个链表,找出它们的第一个公共结点。
    思路:用两个指针扫描”两个链表“,最终两个指针到达 null 或者到达公共结点。
代码:
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
 
        ListNode p1=pHead1;
        ListNode p2=pHead2;
        
        while(p1!=p2){
            
            p1=p1==null?p1=pHead2:p1.next;
            p2=p2==null?p2=pHead1:p2.next;
            
        }
        
        return p1;
    }
}

37.统计一个数字在排序数组中出现的次数。
    思路:定义一个计数变量,循环一次,
代码:
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       
        if(array==null||array.length==0)
            return 0;
        
        int count=0;
        for(int i=0;i<array.length;i++){
            
            if(k==array[i]){
                count++;
            } 
        }
        
        return count;
        
    }
}

38.输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
    思路:假如是空节点,则返回0;
               否则,原树的深度由左右子树中深度较的深度加1,为原树的深度。
代码:
/*
public class TreeNode {
	int val = 0;
	TreeNode left = null;
	TreeNode right = null;
	public TreeNode(int val) {
        this.val = val;
    }
};*/
public class Solution {
	public int TreeDepth(TreeNode pRoot){
        
        if(pRoot==null)
            return 0;
        
        return Math.max(1+TreeDepth(pRoot.left),1+TreeDepth(pRoot.right));
    
    }
}

39.输入一棵二叉树,判断该二叉树是否是平衡二叉树。
    思路:  后续遍历时,遍历到一个节点,其左右子树已经遍历  依次自底向上判断,每个节点只需要遍历一次
代码:
public class Solution {
    
    private boolean isBalanced=true;
    
    public boolean IsBalanced_Solution(TreeNode root) {
                    
        getDepth(root);    
        
        return isBalanced;
    }
    
    public int getDepth(TreeNode root){
        
        if(root==null)
            return 0;
        
        int left=getDepth(root.left);
        int right=getDepth(root.right);
        
        if(Math.abs(left-right)>1)
           isBalanced=false;
        
        return right>left?right+1:left+1;
        
    }
    
}

40.一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
    思路:使用ArrayList,如果没包含就添加,包含就移除
代码:
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.ArrayList;

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        
        ArrayList<Integer> list=new ArrayList<Integer>();
        
        for(int i=0;i<array.length;i++){
            
            if(!list.contains(array[i])){
                list.add(array[i]);
            }else{
                list.remove(new Integer(array[i]));
            }
            
            if(list.size()>1){
                
                num1[0]=list.get(0);
                num2[0]=list.get(1);
                
            }
            
        }
        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值