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

来源:互联网 发布:东邪西毒 欧阳锋 知乎 编辑:程序博客网 时间:2024/05/22 13:46

第三十二题:把数组排成最小的数
题目描述:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{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;    }}
0 0