# 【剑指offer】31-40题

31.求连续子数组（包含负数）的最大和

``````public int FindGreatestSumOfSubArray(int[] array) {
if (array == null || array.length == 0)
return 0;
int cur = array[0];
int greast = array[0];

for (int i = 1; i < array.length; i++) {
if (cur < 0) {
cur = array[i];
}else {
cur += array[i];
}

if (cur > greast) {
greast = cur;
}
}
return greast;
}
``````

32.从1到整数n中1出现的次数

``````public long CountOne2(long n) {
long count = 0; // 1的个数
long i = 1;  // 当前位
long current = 0,after = 0,before = 0;

while((n / i) != 0) {
before = n / (i * 10); // 高位
current = (n / i) % 10; // 当前位
after = n - (n / i) * i;  // 低位

if (current == 0)
//如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数
count = count + before * i;
else if(current == 1)
//如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1
count = count + before * i + after + 1;
else if (current > 1)
// 如果大于1,出现1的次数由高位决定,（高位数字+1）* 当前位数
count = count + (before + 1) * i;
//前移一位
i = i * 10;
}
return count;
}
``````

``````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; // 低位
count += (a+8) / 10 * i;
if(a % 10 == 1){
count += b + 1;
}
}
return count;
}
``````

33.输入一个正整数数组，把数组里所有数字拼接起来排成一个数，打印能拼接出的所有数字中最小的一个

``````public String PrintMinNumber(int [] numbers) {
if(numbers == null || numbers.length == 0)
return "";
int len = numbers.length;
String[] str = new String[len];
StringBuilder sb = new StringBuilder();
for(int i = 0; i < len; i++){
str[i] = String.valueOf(numbers[i]);
}
Arrays.sort(str,new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
String c1 = s1 + s2;
String c2 = s2 + s1;
return c1.compareTo(c2);
}
});

for(int i = 0; i < len; i++){
sb.append(str[i]);
}
return sb.toString();
}
``````

34.丑数是只包含因子2、3和5的数，求从小到大的第N个丑数。

``````public int GetUglyNumber_Solution(int index) {
if (index <= 0)
return 0;
int[] arr = new int[index];
arr[0] = 1;
int multiply2 = 0;
int multiply3 = 0;
int multiply5 = 0;

for (int i = 1; i < index; i++) {
int min = Math.min(arr[multiply2] * 2,Math.min(arr[multiply3] * 3,arr[multiply5] * 5));
arr[i] = min;
if (arr[multiply2] * 2 == min)
multiply2++;
if (arr[multiply3] * 3 == min)
multiply3++;
if (arr[multiply5] * 5 == min)
multiply5++;
}
return arr[index - 1];
}
``````

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

``````public int FirstNotRepeatingChar(String str) {
if (str == null || str.length() == 0)
return -1;
char[] c = str.toCharArray();

for(char item : c) {
if(hash.containsKey(item))
hash.put(item, hash.get(item)+1);
else
hash.put(item, 1);
}

for(int i = 0;i < str.length(); i++){
if (hash.get(str.charAt(i)) == 1) {
return i;
}
}
return -1;
}
``````

36.在数组中的两个数字，如果前面一个数字大于后面的数字，则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P

``````int count = 0;
public int InversePairs(int [] array) {
if(array==null)
return 0;
mergeSort(array,0,array.length-1);
return count;
}

private void mergeSort(int[] data,int start,int end) {
int mid = (start + end) / 2;
if (start < end) {
mergeSort(data, start, mid);
mergeSort(data, mid + 1, end);
merge(data, start, mid, end);
}
}

public void merge(int[] data,int start,int mid,int end) {
int arr[] = new int[end - start + 1];
int c = 0;
int s = start;
int index = mid + 1;
while (start <= mid && index <= end) {
if (data[start] < data[index]) {
arr[c++] = data[start++];
} else {
arr[c++] = data[index++];
count += mid +1 - start;
count %= 1000000007;
}
}

while (start <= mid) {
arr[c++] = data[start++];
}

while (index <= end) {
arr[c++] = data[index++];
}

for (int d : arr) {
data[s++] = d;
}
}
``````

37.输入两个链表，找出它们的第一个公共结点。

``````// 不需要遍历链表的解法
while (p1 != p2){
p1 = (p1 != null ? p1.nextNode : pHead2);
p2 = (p2 != null ? p2.nextNode : pHead1);
}
return p1;
}
``````

38.统计一个数字在排序数组中出现的次数。

``````public int GetNumberOfK(int[] array,int k) {
int result=0;
int mid = array.length/2;

if(array==null || array.length == 0)
return 0;
if(array.length == 1) {
if(array[0] == k)
return 1;
else
return 0;
}

if(k < array[mid])
result += GetNumberOfK(Arrays.copyOfRange(array, 0, mid),k);
else if(k > array[mid])
result += GetNumberOfK(Arrays.copyOfRange(array, mid, array.length),k);
else {
for(int i = mid;i < array.length;i++) {
if(array[i] == k)
result++;
else
break;
}

for(int i = mid - 1;i >= 0;i--) {
if(array[i] == k)
result++;
else
break;
}
}

return result;
}
``````

39.输入一棵二叉树，求该树的深度。从根结点到叶结点依次经过的结点（含根、叶结点）形成树的一条路径，最长路径的长度为树的深度。

``````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.1输入一棵二叉树，判断该二叉树是否是平衡二叉树。

``````public boolean IsBalanced_Solution(TreeNode root) {
if (root == null)
return true;
int left = getDepth(root.left);
int right = getDepth(root.right);
int diff = left - right;
if (diff >= -1 && diff <= 1) {
return true;
}
return false;
}

public int getDepth(TreeNode root) {
if (root == null)
return 0;
int depth = 0;
int leftNode = getDepth(root.left);
int rightNode = getDepth(root.right);
depth = leftNode > rightNode ? leftNode : rightNode;
return depth + 1;
}
``````

40.一个整型数组里除了两个数字之外，其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

``````public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if (array == null)
return;
num1[0] = 0;
num2[0] = 0;
int number = array[0];
for (int i = 1; i < array.length; i++)
number ^= array[i];
// 异或后的数1出现在第几位
int index = 0;
while ((number & 1) == 0) {
number = number >> 1;
index++;
}

for (int i = 0; i < array.length; i++) {
// 判断第index位是不是0
boolean isBit = ((array[i] >> index) & 1) == 0;
if (isBit) {
num1[0] ^= array[i];
} else {
num2[0] ^= array[i];
}
}
}
``````

原文作者： 白夜行515
原文地址: https://blog.csdn.net/baiye_xing/article/details/78428354
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。