21-30题
21. 栈的压入、弹出序列 – 抽象问题具体化
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int[] pushA, int[] popA) {
int len = pushA.length;
int index = 0;
Stack<Integer> stack = new Stack<Integer>();
for (int i = 0; i < len; i++) {
stack.push(pushA[i]);
while (!stack.empty() && index < len && stack.peek() == popA[index]) {
stack.pop();
index++;
}
}
return stack.empty();
}
}
22. 从上往下打印二叉树 – 抽象问题具体化
题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
import java.util.LinkedList;
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> list = new ArrayList<Integer>();
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
if (root != null) {
queue.offerLast(root);
while (!queue.isEmpty()) {
TreeNode temp = queue.pollFirst();
list.add(temp.val);
if (temp.left != null) {
queue.offerLast(temp.left);
}
if (temp.right != null) {
queue.offerLast(temp.right);
}
}
}
return list;
}
}
23. 二叉搜索树的后序遍历序列 – 抽象问题具体化
题目描述
输入一个非空整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
public class Solution {
public static boolean VerifySquenceOfBST(int[] sequence) {
// 二叉搜索树的中序遍历是顺序的
// 那么后序遍历的话,根节点一定大于其左子树,小于其右子树
return VerifySquenceOfBSTCore(sequence, 0, sequence.length - 1);
}
public static boolean VerifySquenceOfBSTCore(int[] sequence, int start,
int end) {
if (sequence == null || (end - start) < 0) {
return false;
}
int root = sequence[end];
int index = start;
for (; index < end; index++) {
if (sequence[index] > root) {
break;
}
}
for (int temp = index + 1; temp < end; temp++) {
if (sequence[temp] < root) {
return false;
}
}
boolean left = true;
if (index - 1 - start > 0) {
left = VerifySquenceOfBSTCore(sequence, start, index - 1);
}
boolean right = true;
if (end - 1 - index > 0) {
right = VerifySquenceOfBSTCore(sequence, index, end - 1);
}
return left && right;
}
}
24. 二叉树中和为某一值的路径 – 抽象问题具体化
题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ArrayList<ArrayList<Integer>> allPath = new ArrayList<ArrayList<Integer>>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,
int target) {
if (root == null || target == 0) {
return allPath;
}
ArrayList<Integer> path = new ArrayList<Integer>();
int currentSum = 0;
FindPathCore(root, target, path, currentSum);
return allPath;
}
public void FindPathCore(TreeNode root, int target,
ArrayList<Integer> path, int currentSum) {
currentSum += root.val;
path.add(root.val);
if (currentSum == target && root.left == null && root.right == null) {
ArrayList<Integer> temp = new ArrayList<Integer>(path);
allPath.add(temp);
}
if (root.left != null) {
FindPathCore(root.left, target, path, currentSum);
}
if (root.right != null) {
FindPathCore(root.right, target, path, currentSum);
}
// 模拟数据结构-栈
// 在返回父节点之前,删除路径上的当前结点
path.remove(path.size() - 1);
}
}
25. 复杂链表的复制 – 复杂问题简单化
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead) {
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
public void CloneNodes(RandomListNode pHead) {
RandomListNode pNode = pHead;
while (pNode != null) {
RandomListNode pCloned = new RandomListNode(pNode.label);
pCloned.next = pNode.next;
pCloned.random = null;
pNode.next = pCloned;
pNode = pCloned.next;
}
}
public void ConnectSiblingNodes(RandomListNode pHead) {
RandomListNode pNode = pHead;
while (pNode != null) {
RandomListNode pCloned = pNode.next;
if (pNode.random != null) {
pCloned.random = pNode.random.next;
}
pNode = pCloned.next;
}
}
public RandomListNode ReconnectNodes(RandomListNode pHead) {
RandomListNode pNode = pHead;
RandomListNode pClonedHead = null;
RandomListNode pClonedNode = null;
if (pNode != null) {
pClonedHead = pClonedNode = pNode.next;
pNode.next = pClonedNode.next;
pNode = pNode.next;
}
while (pNode != null) {
pClonedNode.next = pNode.next;
pClonedNode = pClonedNode.next;
pNode.next = pClonedNode.next;
pNode = pNode.next;
}
return pClonedHead;
}
}
26. 二叉搜索树与双向链表 – 复杂问题简单化
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeNode Convert(TreeNode root) {
if (root == null)
return null;
if (root.left == null && root.right == null)
return root;
TreeNode left = Convert(root.left);
TreeNode p = left;
while (p != null && p.right != null) {
p = p.right;
}
if (left != null) {
p.right = root;
root.left = p;
}
TreeNode right = Convert(root.right);
if (right != null) {
right.left = root;
root.right = right;
}
return left != null ? left : root;
}
}
27. 字符串的排序 – 复杂问题简单化
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
public class Solution {
ArrayList<String> result = new ArrayList<String>();
public ArrayList<String> Permutation(String str) {
char[] strtemp = str.toCharArray();
int len = str.length();
PermutationCore(strtemp, 0, len);
// 顺序可能和测试用例不一样,所以排序一下
Collections.sort(result);
return result;
}
public void PermutationCore(char[] str, int index, int len) {
if (index == len - 1) {
result.add(String.valueOf(str));
} else {
// 不保存重复的元素,避免"baa"→"aba""aab"的情况
Set<Character> charSet = new HashSet<Character>();
for (int i = index; i < len; i++) {
if (index == i || !charSet.contains(str[i])) {
charSet.add(str[i]);
swap(str, index, i);
PermutationCore(str, index + 1, len);
swap(str, index, i);
}
}
}
}
public void swap(char[] str, int index, int i){
char temp = str[index];
str[index] = str[i];
str[i] = temp;
}
}
28. 数组中出现次数超过一半的数字 – 时间效率
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
public class Solution {
public int MoreThanHalfNum_Solution(int[] array) {
if (array == null) {
return 0;
}
int len = array.length;
return QuickSort(array, 0, len - 1, len / 2);
}
public int QuickSort(int[] array, int start, int end, int middle) {
int partitionIndex = partition(array, start, end, middle);
while (partitionIndex != middle) {
if (partitionIndex > middle) {
partitionIndex = partition(array, start, partitionIndex - 1,
middle);
} else {
partitionIndex = partition(array, partitionIndex + 1, end,
middle);
}
}
int result = array[partitionIndex];
if (!check(array, result, end + 1)) {
return 0;
}
return result;
}
public int partition(int[] array, int start, int end, int middle) {
int pivot = start;
int index = pivot + 1;
for (int i = index; i < array.length; i++) {
if (array[i] < array[pivot]) {
swap(array, i, index);
index++;
}
}
swap(array, pivot, index - 1);
return index - 1;
}
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public boolean check(int[] array, int number, int length) {
int count = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == number) {
count++;
}
}
if (count * 2 <= length) {
return false;
}
return true;
}
}
public class Solution {
public int MoreThanHalfNum_Solution(int[] array) {
if (array == null) {
return 0;
}
int result = array[0];
int count = 1;
for (int i = 1; i < array.length; i++) {
if (count == 0) {
result = array[i];
count = 1;
} else if (result == array[i]) {
count++;
} else {
count--;
}
}
int ans = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == result) {
ans++;
}
}
if (ans * 2 <= array.length) {
return 0;
}
return result;
}
}
29. 最小的k个数 – 时间效率
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
public static ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
if (input == null || k == 0 || k > input.length) {
return result;
}
for (int i = 0; i < input.length; i++) {
result.add(input[i]);
}
Collections.sort(result);
int index = result.size();
while (index > k) {
index--;
result.remove(index);
}
return result;
}
}
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
public static ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>(k);
if (input == null || k == 0 || k > input.length) {
return result;
}
for (int i = 0; i < input.length; i++) {
if (result.size() < k) {
result.add(input[i]);
} else {
Collections.sort(result);
if (result.get(k - 1) > input[i]) {
result.remove(k - 1);
result.add(input[i]);
}
}
}
return result;
}
}
30. 连续子数组的最大和 – 时间效率
题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
public class Solution {
public static int FindGreatestSumOfSubArray(int[] array) {
if (array == null) {
return 0;
}
int sum = 0;
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
sum += array[i];
if (sum > max) {
max = sum;
}
if (sum <= 0) {
sum = 0;
}
}
return max;
}
}