31-40题
31. 1-n 整数中1出现的次数 – 时间效率
题目描述
求出1-13的整数中1出现的次数,并算出100-1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int count =0;
for (int i = 1; i <= n; i++) {
String str = String.valueOf(i);
if(str.contains("1")){
for (int j = 0; j < str.length(); j++) {
if(str.charAt(j)=='1'){
count++;
}
}
}
}
return count;
}
}
32. 把数组排成最小的数 – 时间效率
题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Solution {
public String PrintMinNumber(int[] numbers) {
ArrayList<String> str = new ArrayList<String>();
for (int i = 0; i < numbers.length; i++) {
str.add(String.valueOf(numbers[i]));
}
/*
* a,b
* ab<ba,a<b
* ab>ba,a>b
*/
Collections.sort(str, new Comparator<String>() {
public int compare(String str1, String str2) {
String s1 = str1 + str2;
String s2 = str2 + str1;
return s1.compareTo(s2);
}
});
StringBuilder sb = new StringBuilder();
for (String string : str) {
sb.append(string);
}
return sb.toString();
}
}
33. 丑数 – 时间效率与空间效率的平衡
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
import java.util.LinkedList;
public class Solution {
public int GetUglyNumber_Solution(int index) {
/**
* 首先,丑数不断除以2 or 3 or 5 最后等于1
* 前15个丑数,1,2,3,4,5,6,8,9,10,12,15,16,18,20,24...
* 1*2,1*3,1*5,
* 2*2,2*3,2*5,...,3*2,3*3,3*5
* 类似于打表,但是要注意顺序
*/
if (index < 7) {
return index;
}
LinkedList<Integer> list = new LinkedList<Integer>();
int num = 1;
list.add(num);
// 三个指针
int a = 0;
int b = 0;
int c = 0;
while (list.size() < index) {
num = Math.min(Math.min(list.get(a) * 2, list.get(b) * 3),
list.get(c) * 5);
if (num == list.get(a) * 2)
a++;
if (num == list.get(b) * 3)
b++;
if (num == list.get(c) * 5)
c++;
list.add(num);
}
return num;
}
}
34. 第一个只出现一次的字符位置 – 时间效率与空间效率的平衡
题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
public class Solution {
public int FirstNotRepeatingChar(String str) {
int[] hashtable = new int[26 + 26 + 6];
for (int i = 0; i < str.length(); i++) {
hashtable[str.charAt(i) - 'A']++;
}
for (int i = 0; i < str.length(); i++) {
if (hashtable[str.charAt(i) - 'A'] == 1) {
return i;
}
}
return -1;
}
}
35. 数组中的逆序对 – 时间效率与空间效率的平衡
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。
即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
public class Solution {
public int InversePairs(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int[] copy = new int[array.length];
for (int i = 0; i < array.length; i++) {
copy[i] = array[i];
}
int count = InversePairsCore(array, copy, 0, array.length - 1) % 1000000007;// 数值过大求余
return count;
}
private int InversePairsCore(int[] array, int[] copy, int low, int high) {
if (low == high) {
return 0;
}
int mid = (low + high) >> 1;
int leftCount = InversePairsCore(array, copy, low, mid) % 1000000007;
int rightCount = InversePairsCore(array, copy, mid + 1, high) % 1000000007;
int count = 0;
int i = mid;
int j = high;
int locCopy = high;
while (i >= low && j > mid) {
if (array[i] > array[j]) {
count += j - mid;
copy[locCopy--] = array[i--];
if (count >= 1000000007)// 数值过大求余
{
count %= 1000000007;
}
} else {
copy[locCopy--] = array[j--];
}
}
for (; i >= low; i--) {
copy[locCopy--] = array[i];
}
for (; j > mid; j--) {
copy[locCopy--] = array[j];
}
for (int s = low; s <= high; s++) {
array[s] = copy[s];
}
return (leftCount + rightCount + count) % 1000000007;
}
}
36. 两个链表的第一个公共结点 – 时间效率与空间效率的平衡
题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
// 计算长度差
int len1 = 1, len2 = 1;
ListNode pNode1 = pHead1;
ListNode pNode2 = pHead2;
while ((pNode1 = pNode1.next) != null) {
len1++;
}
while ((pNode2 = pNode2.next) != null) {
len2++;
}
if (len1 > len2) {
int n = len1 - len2;
while (n > 0) {
pHead1 = pHead1.next;
n--;
}
} else {
int n = len2 - len1;
while (n > 0) {
pHead2 = pHead2.next;
n--;
}
}
ListNode result = new ListNode(0);
boolean flag = true;
while (pHead1 != null) {
if (pHead1.val == pHead2.val && flag) {
result = pHead1;
// System.out.println(result.val);
flag = false;
} else if (pHead1 != pHead2) {
result = null;
// 可以重新给结果赋值
flag = true;
}
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return result;
}
}
// 看到一个大佬的写法,画个图理解一下
/*两个链表 6,5,4,3,2,1; 5,4,2,2,1
6 5 4 3 5 4 2 2 1
2 1 null
5 4 2 6 5 4 3 2 1
*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (p1 != p2) {
p1 = p1 == null ? pHead2 : p1.next;
p2 = p2 == null ? pHead1 : p2.next;
}
return p1;
}
}
37. 数字在排序数组中出现的次数 – 知识迁移能力
题目描述
统计一个数字在排序数组中出现的次数。
public class Solution {
public int GetNumberOfK(int[] array, int k) {
int number = 0;
int len = array.length;
// 有序数组,二分查找
if (array != null && len > 0) {
int first = GetFirstK(array, k, 0, len - 1);
int last = GetLastK(array, k, 0, len - 1);
if (first > -1 && last > -1) {
// System.out.println(last+" "+first);
number = last - first + 1;
}
}
return number;
}
public int GetFirstK(int[] array, int k, int start, int end) {
if (start > end) {
return -1;
}
int middle = (start + end) / 2;
int middledata = array[middle];
if (middledata == k) {
if (middle > 0 && array[middle - 1] < k || middle == 0) {
return middle;
} else {
end = middle - 1;
}
} else if (middledata > k) {
end = middle - 1;
} else {
start = middle + 1;
}
return GetFirstK(array, k, start, end);
}
public int GetLastK(int[] array, int k, int start, int end) {
if (start > end) {
return -1;
}
int middle = (start + end) / 2;
int middledata = array[middle];
while (start <= end) {
if (middledata == k) {
if (middle < array.length - 1 && array[middle + 1] != k
|| middle == array.length - 1) {
return middle;
} else {
start = middle + 1;
}
} else if (middledata < k) {
start = middle + 1;
} else {
end = middle - 1;
}
middle = (start + end) / 2;
middledata = array[middle];
}
return -1;
}
}
38. 二叉树的深度 – 知识迁移能力
题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public int TreeDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
return left > right ? left + 1 : right + 1;
}
}
39. 平衡二叉树 – 知识迁移能力
题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return getDepth(root) != -1;
}
private int getDepth(TreeNode root) {
if (root == null)
return 0;
// 后序遍历
int left = getDepth(root.left);
if (left == -1)
return -1;
int right = getDepth(root.right);
if (right == -1)
return -1;
return Math.abs(left - right) > 1 ? -1 : 1 + Math.max(left, right);
}
}
40. 数组中只出现一次的数字 – 知识迁移能力
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int[] array, int[] num1, int[] num2) {
int length = array.length;
if (length < 2) {
return;
}
int bitResult = 0;
for (int i = 0; i < length; ++i) {
bitResult ^= array[i];
}
int index = findFirst1(bitResult);
num1[0] = 0;
num2[0] = 0;
for (int i = 0; i < length; ++i) {
if (isBit1(array[i], index)) {
num1[0] ^= array[i];
} else {
num2[0] ^= array[i];
}
}
}
private int findFirst1(int bitResult) {
int index = 0;
while (((bitResult & 1) == 0) && index < 32) {
bitResult = bitResult >> 1;
index++;
}
return index;
}
private boolean isBit1(int target, int index) {
target = target >> index;
return (target & 1) == 1;
}
}