剑指Offer【牛客网】刷题(七)

31、整数中1出现的次数

题目描述:求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
解题思路:把每个数转化成string,数其中1的个数

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int count = 0;
        for(int i = 1; i <= n; i++) {
            String str = i + "";
            for(int j = 0; j < str.length(); j++) {
                char c = str.charAt(j);
                if(c == '1') {
                    count ++;
                }
            }
        }
        return count;
    }
}

32、把数组排成最小的数

题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323
解题思路:即把数组中最小的数排在最前

import java.util.Arrays;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        
       if(numbers == null || numbers.length == 0) {
            return "";
        }

        int len = numbers.length;
        String[] strs = new String[len];
        for(int i = 0; i < len; i++) {
            strs[i] = numbers[i] + "";
        }

        Arrays.sort(strs);
        
        for(int i = 0; i < len - 1; i++) {
            for(int j = i + 1; j < len; j++) {
                String str1 = strs[i];
                String str2 = strs[j];

                if(str1.charAt(0) == str2.charAt(0)) {
                    int len1 = str1.length();
                    int len2 = str2.length();

                    int min_len = Math.min(len1, len2);
                    int max_len = Math.max(len1, len2);
                    for(int k = 0; k < max_len; k++) {
                        if(k < min_len) {
                            if(str1.charAt(k) > str2.charAt(k)) {
                                String temp = strs[j];
                                strs[j] = strs[i];
                                strs[i] = temp;
                                break;
                            }
                        }else {

                            if(len1 > min_len) {
                                char c = str1.charAt(k);
                                if(c > str2.charAt(0)) {
                                    String temp = strs[j];
                                    strs[j] = strs[i];
                                    strs[i] = temp;
                                    break;
                                }
                            }else if(len2 > min_len) {
                                char c = str2.charAt(k);
                                if(c < str1.charAt(0)) {
                                    String temp = strs[j];
                                    strs[j] = strs[i];
                                    strs[i] = temp;
                                    break;
                                }
                            }


                        }
                    }
                }
            }
        }
        
        String result = "";
        for(String s: strs) {
            result += s;
        }
   
        return result;
    }
}

33、丑数

题目描述:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

解题思路:建立一个长度为N的数组,从1开始每计算出下一个丑数变存入数组中,则数组的最后一个值就是我们所需要的值。至于如何计算下一个丑数,我们可以用三个指针p2, p3, p5来分别指向可以乘以2、3、5的数在数组中的下标,比较各自指向的数乘以2、3、5后的值,取最小值,最小值的那个指针下标加一,以此类推

public class Solution {
    public int GetUglyNumber_Solution(int index) {
        
        if(index <= 0) {
            return 0;
        }
        
        int[] uglys = new int[index];
        uglys[0] = 1;
        
        int pointer2 = 0;
        int pointer3 = 0;
        int pointer5 = 0;
        
        for(int i = 1; i < index; i++) {
            int next = Math.min(uglys[pointer2]*2, Math.min(uglys[pointer3]*3, uglys[pointer5]*5));
            if(next == uglys[pointer2]*2) {
                pointer2++;
            }
            if(next == uglys[pointer3]*3) {
                pointer3++;
            }
            if(next == uglys[pointer5]*5) {
                pointer5++;
            }
            uglys[i] = next;
        }
        
        return uglys[index-1];
    }
}

34、第一个只出现一次的字符

题目描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)

解题思路:用两个指针指向字符串头尾向中间遍历比较.

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        
        int len = str.length();
        for(int i = 0; i < len; i++) {
            char c = str.charAt(i);
            boolean isSingle = true;
            
            int m = 0; 
            int n = len - 1;
            while(m <= n) {
                char c1 = str.charAt(m);
                char c2 = str.charAt(n);
                
                if(m == i && n != i) {
                    if(c2 == c) {
                        isSingle = false;
                        break;
                    }
                }
                if(m != i && n == i) {
                    if(c1 == c) {
                        isSingle = false;
                        break;
                    }
                }
                if(m == i && n == i) {
                    
                }
                if(m != i && n != i) {
                    if(c == c1 || c == c2) {
                        isSingle = false;
                        break;
                    }
                }
                m++;
                n--;
                }
            if(isSingle) {
                return i;
            }
        }
        return -1;
    }
}

35、数组中的逆序对

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

解题思路:这题实质就是排序,将每一个数按位移动后排成从小到大的顺序所需的移动次数即题解。不管时间复杂度的话,使用冒泡排序,依次比较,就可以得出结果。
但是题目有时间限制,采用归并排序。归并排序的核心是计算移动次数counter += (mid-i+1)

long counter = 0;

    public int InversePairs(int [] array) {
        if(array==null||array.length==0){
            return -1;
        }
        mergeSort(array);
        for(Integer i: array) {
            System.out.print(i+ " ");
        }
        System.out.println();
        return (int)(counter%1000000007);
    }
    public void mergeSort(int[] array){
        sort(array,0,array.length-1);
    }
    public void sort(int[] array,int left,int right){
        if(left<right){
            int mid = (left+right)/2;
            sort(array,left,mid);
            sort(array,mid+1,right);
            merge(array,left,mid,right);
        }/*else if(left == right) {
            for(Integer i: array) {
                System.out.print(i + " ");

            }
            System.out.println();
        }*/
    }
    public void merge(int[] array, int left,int mid, int right){
        int[] temp = new int[right-left+1];
        int i = left, j = mid + 1, k = 0;
        while(i<=mid&&j<=right){
            if(array[i]<=array[j]){
                temp[k++] = array[i++];
            }else{
                temp[k++] = array[j++];
                counter += mid - i + 1;//core
            }
        }
        while(i<=mid){
            temp[k++] = array[i++];
        }
        while(j<=right){
            temp[k++] = array[j++];
        }
        for(int p=0;p<temp.length;p++){
            array[left+p] = temp[p];
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值