牛客网 剑指Offer,一些值得记住的小题(三)

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

import java.util.*;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> list=new ArrayList<String>();
        if(str.length()==0){
            return list;
        } 
        char [] temp=str.toCharArray();
        HashSet<String > s = new HashSet<String>();
        Fund(s,temp,0);
        list.addAll(s);
        Collections.sort(list);
        return list;
    }
    void Fund(HashSet<String > s,char[] str,int k){
        if(str.length==k){
            s.add(new String(str));
            return ;
        } 
        for(int i=k;i<str.length;i++){
            Swap(str,i,k);
            Fund(s,str,k+1);
            Swap(str,i,k);
         }    
    }
    void Swap(char [] str,int i,int j){
        if(i!=j){
            char temp = str[i];
            str[i]=str[j];
            str[j]=temp;
        }
    }
}

解析:图是我从网上找的,本题考查的知识点是全排列,Fund(HashSet<String> s,char[] str,int k),该函数的意思是为str中从k开始进行全排序,并且存在s中,因为有可能有重复的数字所以可以加判断条件,即有相同的数字不swap(),在这里我运用了将hashset放进list后再去重排序(删除重复元素)的处理。


14.数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        Arrays.sort(array);
        for(int i=0;i<array.length%2+array.length/2;i++){
            if(array[i]==array[i+array.length/2]){
                return  array[i];
            }
        }
        return 0;
    }
}
解析:本题并不难,但是我感觉很新颖,思路是将数组排序后如果一个数与半个数组长度之后的数字相等,则返回这个数字。


15.求出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*=10){
            int a=n/i;
            int b=n%i;
            if(a%10==1){
                count=count+(a+8)/10*i+(b+1);
            }else{
                count=count+(a+8)/10*i;
            }
        }
        return count;
    }
}
解析:

例如:2312这个数
先判断个位会出现多少个1
再判断十位,如果这位是1(即a%10==1)则主要加上这位置后的数的数量
再判断百位,如果这位是1(即a%10==1)则主要加上这位置后的数的数量,如果不是则count+100
再判断千位,如果这位是1(即a%10==1)则主要加上这位置后的数的数量,如果不是则count+1000

这个是牛客网上标准一些的说法:

链接:https://www.nowcoder.com/questionTerminal/bd7f978302044eee894445e244c7eee6
来源:牛客网

/*设N = abcde ,其中abcde分别为十进制中各位上的数字。如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。① 如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100~199,1100~1199,2100~2199,,...,11100~11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。② 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100~199,1100~1199,2100~2199,,....,11100~11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共114个,等于低位数字(113)+1。③ 如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100~199,1100~1199,2100~2199,...,11100~11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。*/ 


16.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class Solution {
    public String PrintMinNumber(int [] numbers) {
     if(numbers.length==0||numbers==null){
            return "";
        }
        String[] str = new String[numbers.length];
        StringBuilder ss = new StringBuilder();
        for(int i=0;i<numbers.length;i++){
            str[i]=String.valueOf(numbers[i]);
        }
        Arrays.sort(str,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<str.length;i++){
            ss.append(str[i]);
        }
        return ss.toString();
    }
}
解析:关键在于自己定义了比较方式, Array(str,new Comparator<String>),经过这个函数后, 
最小的这书就以数组的形式存在str中(排序后),然后再放进ss。


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

import java.util.ArrayList;
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if(index<7){
            return index;
        }
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(0,1);
        int a=0,b=0,c=0;
        for(int i=1;i<index;i++){
            list.add(i,min(list.get(a)*2,min(list.get(b)*3,list.get(c)*5)));
            if(list.get(i)==list.get(a)*2)a++;
            if(list.get(i)==list.get(b)*3)b++;
            if(list.get(i)==list.get(c)*5)c++;
        }
        return list.get(index-1);
    }
    int min(int i,int j){
        return (i<j)?i:j;
    }
}
解析:丑数其实就是将1分别*2,*3,*5以及这些数都*2,*3,*5后得到的数的集合(7之前全都是丑数),并且每一个丑数*2,*3,*5后都是丑数,所以先将1放进list,再开始循环,a指向的数表示当前的数*2还没加到list中,b指向的数表示当前的数*3还没有加到list中,c 指向的数表示当前的数*5还没有加到list中。


18。在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置

import java.util.HashSet;
public class Solution {
    public int FirstNotRepeatingChar(String str) {
        if(str.length()==0){
            return -1;
        }
        HashSet<Character> set = new HashSet<Character>();
        char [] strlist = str.toCharArray();
        for(int i=0;i<str.length();i++){
        	if(set.contains(strlist[i])){
        		continue;
        	}else{
        		int j;
        		int flag=0;
        		for(j=i+1;j<str.length();j++){
        			if(strlist[i]==strlist[j]){
        				set.add(strlist[i]);
        				flag=1;
        				break;
        			}
        		}
        		if(flag==0){
        			return i;
        		}
        	}
        }
        return -1;
    }
}

解析:思路是将重复的数字放进list,第一个出现在list里没有的数字,然后遍历这个数后面的所有数,若发现有重复则继续加进list,若没有则返回这个数。




猜你喜欢

转载自blog.csdn.net/shl_shl/article/details/68483890
今日推荐