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];
}
}