剑指Offer题目JAVA版思路与代码(九)

第三十二题:把数组排成最小的数
题目描述:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
思路:
可以给出一个新的定义:两个数a、b,如果ab>ba,则定义a大于b,反之,则a小于b;根据此定义将数组中的所有数从小到大排序,然后依序组合成的数字就是最小数字。
代码:

import java.util.ArrayList;
import java.util.*;
public class Solution {
    public String PrintMinNumber(int [] numbers) {
        String result = "";
        ArrayList<String> ret = new ArrayList<String>();
        if(numbers == null || numbers.length == 0){
            return result;
        }
        for (int i = 0; i < numbers.length; i++) {
            ret.add(String.valueOf(numbers[i]));
        }
        Collections.sort(ret, new Comparator<String>(){


            public int compare(String str1, String str2){
                String s1 = str1+str2;
                String s2 = str2+str1;
                return s1.compareTo(s2);
            }
        });
        for(int i = 0; i<ret.size(); i++) {
            result += ret.get(i);
        }
        return result;
    }

}

第三十三题:丑数
题目描述:
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:
首先,要正确地理解丑数的定义,他的因子中除了1和本身之外就只能有2或3或5,除此之外的因子出现就不算是丑数。
其次,如果思路是:将1到n每个数字根据定义判断是不是丑数,然后一直判断到出现第n个丑数,这样的做法未免太过于耗时,做了不少无用功。所以有效的做法是:假设已有一个数组是一组丑数,数组最后一个丑数是u,则要知道下一个丑数的话,直接计算会快很多。取三个指针,分别指向数组中的a、b、c,使得2a大于u,3b大于u,5c大于u;然后只要比较2a,3b,5c的大小,取最小的那个就是数组下一个丑数。至于三个指针的选取,以为是数组是依次计算得到的,所以指针开始都是之前第一个数1,随着计算的进行一步步推进即可。
代码:

public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index <= 0){
            return 0;
        }
        int[] uglynumbers = new int[index];
        uglynumbers[0] = 1;
        int nextuglyindex = 1;

        int m2 = 0;
        int m3 = 0;
        int m5 = 0;
        while (nextuglyindex<index){
            int nextnum = Min(uglynumbers[m2]*2, uglynumbers[m3]*3, uglynumbers[m5]*5);
            uglynumbers[nextuglyindex] = nextnum;

            while(uglynumbers[m2]*2 <= nextnum){
                m2++;
            }
            while(uglynumbers[m3]*3 <= nextnum) {
                m3++;
            }
            while(uglynumbers[m5]*5 <= nextnum) {
                m5++;
            }

            nextuglyindex++;
        }
        return uglynumbers[index-1];
    }
    public int Min(int n1, int n2, int n3) {
        int min = (n1 < n2 ? n1 : n2);
        min = (min < n3 ? min : n3);
        return min;
    }
}

第三十四题:第一次只出现一次的字符
题目描述:
在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置。
思路:
需要一个长度为256的数组,初始化为0。然后扫描字符串,以字符的ASCII码最为数组的下标,存储出现的次数。之后第二次扫描该字符串,找到hash表中对应字符出现的次数是否为1。为1则输出数组中对应的位置i。
代码:

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        if (str == null || str.length() == 0){
            return -1;
        }
        int[] helper = new int[256];
        for (int i = 0; i < 256; i++) {
            helper[i] = 0;
        }
        for (int i = 0; i < str.length(); i++) {
            helper[str.charAt(i)-'0'] += 1;
        }
        int ret = -1;
        for (int i = 0; i < str.length(); i++) {
            if (helper[str.charAt(i)-'0'] == 1){
                ret = i;
                break;
            }
        }
        return ret;
    }
}
点赞