02、实现Singleton模式
03、二维数组中的查找
public static boolean findInPartiallySortedMatrix(int[][] array, int targetNumber) {
int row = array.length;
int col = array[0].length;
int i = 0, j = col - 1;
while (i < row && j >= 0) {
if (array[i][j] > targetNumber) {
j--;
} else if (array[i][j] < targetNumber) {
i++;
} else return true;
}
return false;
}
04、替换空格
str.replace(
"
"
,
""
);
05、从尾到头打印链表
public static void printListReversingly_Iteratively(Node head) {
if (head == null) {
return;
}
stack<Node> nodes = new stack<Node>();
while (head != null) {
nodes.push(head);
head = head.next;
}
while (!nodes.isEmpty) {
System.out.println(nodes.pop().value);
}
}
public static void printListReversingly_Recursively(Node head) {
if (head != null) {
if (head.next != null) {
printListReversingly_Recursively(head.next);
} else System.out.println(head.value);
}
}
06、重建二叉树
根据先序遍历序列和中序遍历序列重建二叉树
public TreeNode reConstructBinaryTree(int[] preOrder,int[] inOrder) {
if (preOrder.length != inOrder.length) throws Exception;
int index = preOrder.length - 1;
if (index == 0) return null;
return reConstructBinaryTree(preOrder, 0, index, inOrder, 0, index);
}
private TreeNode reConstructBinaryTree(int[] preOrder,int preStart, int preEnd, int[] inOrder, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd)
return null;
TreeNode root = new TreeNode(preOrder[preStart]);
for (int i = inStart; i <= inEnd; i++) {
if (inOrder[i] == preOrder[preStart]) {
root.left = reConstructBinaryTree(preOrder, preStart + i - inStart, index, inOrder, inStart, i - 1);
root.right = reConstructBinaryTree(preOrder, preStart + i - inStart + 1, preEnd, inOrder, i + 1, inEnd);
}
}
return root;
}
07、用两个栈实现队列
private Stack<Item> appendStack = new Stack<Item>();
private Stack<Item> deleteStack = new Stack<Item>();
public void appendTail(Item item) {
appendStack.push(item);
}
public item deleteHead() {
if (deleteStack.isEmpty()) {
while(!appendStack.isEmpty()) {
deleteStack.push(appendStack.pop());
}
}
if (deleteStack.isEmpty())
throws new Exception("队列为空,不能删");
return deleteStack.pop();
}
08、旋转数组的最小数字
借鉴二分查找法
public int minInReversingList(int[] numbers) {
if(numbers == null)
throws new Exception("数组为空"):
int index1 = 0;
int index2 = numbers.length - 1;
int indexMid = (index1 + index2) / 2;
while (numbers[index1] >= numbers[index2]) {
if (index2 - index1 == 1) {
indexMid = index2;
break;
}
if (numbers[index1] == numbers[index2] || numbers[indexMid] == numbers[index2])
return minInOrder(numbers, index1, index2);
if (numbers[indexMid] >= numbers[index1]) {
index1 = indexMid;
} else if(numbers[indexMid] <= numbers[index2]) {
index2 = indexMid;
}
}
}
private int minInOrder(int[] arr, int startIndex, int endIndex) {
int result = numbers[startIndex];
for (int i = startIndex; i <= endIndex; i++) {
if (numbers[i] < result)
result = numbers[i];
}
return result;
}
09、斐波那契数列求和
调用递归效率低下,因此选择从下往上计算。拓展:青蛙跳台阶。
public int fibonacciNormal(int n) {
if (n < 0)
throws new Exception("n 必须 >= 0");
int[] result = {0, 1};
if (n < 2) return result[n];
int n1 = 1, n2 = 1, sn = 0;
for(int i = 2; i < n; i++) {
sn = n1 + n2;
n1 = n2;
n2 = sn;
}
return sn;
}
10、二进制中1的个数
除法效率低下,尽量使用与运算。右移数字i并判1,如果遇到负数会陷入死循环。因此左移1,依次与运算。
public int countOfNumberOne_1(int number) {
int count = 0;
int flag = 1;
while(flag != 0) {
if(number & flag != 0)
count++;
flag << 1;
}
return count;
}
public int countOfNumberOne_1(int number) {
int count = 0;
while (num != 0) {
count++;
num = num & (num - 1);
}
return count;
}
DAY 2 2017/3/28
11、数值的整数次方
public double pow(double base, int exponent) {
if (exponent == 0)
return 1;
if (exponent<0) {
exponent = - exponent;
base = 1/base; //数学上规定n个a相乘表示为a×a×a×a×...=a^n,其中 a≠0。
}
return (exponent % 2 == 0) ? pow(base*base, exponent >> 1) : base*pow(base*base, exponent >> 1); //右移比除法效率高
}
12、打印1到最大的n位数
当输入n很大的时候,我们求最大的n位数是不是用整型(int)或者长整型(long long)都会溢出?也就是说我们需要考虑大数问题。最常用的也是最容易的用字符串或者数组表达大数。
public void print1ToMaxOfNDigits(int n) {
if (n <= 0) {
System.out.println("输入出错!");
return;
}
int[] number = new int[n];
while (!increment(number)) {
print(number);
}
}
private boolean increment(int[] number) {
boolean isOverflow = false;
int nTakeOver = 0; // 进位
for (int i = number.length - 1; i >= 0; i--) {
int nSum = number[i] + nTakeOver; //nTakeOver使用一次后即跳出循环,不用清零
if (i == number.length - 1) // 如果是最低位加1
nSum++;
if (nSum >= 10) {
if (i == 0)
isOverflow = true;
else {
nTakeOver = 1;
number[i] = nSum - 10;
}
} else {
number[i] = nSum;
break; // 最低位加1后有进位会循环改变前面的位,没有进位跳出循环,前面的位不变
}
}
return isOverflow;
}
// 打印一个数,循环遍历数组,从不为0的位开始打印
private void print(int[] number) {
boolean isValid = false;
for (int i = 0; i < number.length; i++) {
if (!isValid && number[i] != 0)
isValid = true;
if (isValid)
System.out.print(number[i]);
}
System.out.println();
}
13、O(1)时间删除链表节点
public void deleteNode(ListNode head, ListNode deListNode){
if (deListNode == null || head == null)
return;
if (deListNode.next != null){ //要删除的不是尾节点
deListNode.data = deListNode.next.data;
deListNode.next = deListNode.next.next;
} else if (head == deListNode) { //只有一个节点,删除头(尾)结点
head = null;
} else { //有多个节点,删除尾结点
ListNode pinitListNode = head;
while (pinitListNode.next.next != null) {
pinitListNode = pinitListNode.next;
}
pinitListNode.next = null;
}
}
14、调整数组使奇数位于前面
public void reorderArray(int[] array) {
if (array == null) return;
int pLeft = 0;
int pRight = array.length - 1;
while (pLeft < pRight) {
while (pLeft < pRight && isOdd(array[pLeft])) {
pLeft++;
}
while (pLeft < pRight && !isOdd(array[pRight])) {
pRight--;
}
if (pLeft < pRight) {
int temp = array[pLeft];
array[pLeft] = array[pRight];
array[pRight] = temp;
}
}
}
private boolean isOdd(int num) {
return num % 2 != 0;
}
15、链表中倒数第K个节点
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0)
return null;
ListNode pAhead = head, pBehind;
for (int i = 0; i < k - 1; i++) {
if (pAhead.next != null) {
pAhead = pAhead.next;
} else return null;
}
pBehind = head;
while (pAhead.next != null) {
pAhead = pAhead.next;
pBehind = pBehind.next;
}
return pBehind;
}
16、反转链表
public ListNode reverseListNode(ListNode head) {
ListNode pPrev = null, pNode = head;
while (pNode != null) {
ListNode pNext = pNode.next;
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pPrev;
}
17、合并两个排序的链表
public ListNode mergeSortedListNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null) return pHead2;
else if (pHead2 == null) return pHead1;
ListNode pMergedHead = null;
if (pHead1.value < pHead2.value){
pMergedHead = pHead1;
pMergedHead.next = Merge(pHead1.next, pHead2);
}else{
pMergedHead = pHead2;
pMergedHead.next = Merge(pHead1, pHead2.next);
}
return pMergedHead;
}
18、树的子结构
分两步:第一步在树A中找到和B的根节点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。
public boolean isSubtree(Node root1, Node root2) {
if (root2 == null) return true;
if (root1 == null) return false;
return equals(root1, root2) || isSubtree(root1.left, root2) || isSubtree(root1.right, root2);
}
private boolean equals(Node root1, Node root2) {
if (root2 == null) return true;
if (root1 == null) return false;
if (root1.data != root2.data) return false; // Should use .equals if Node.data isn't primitive
return equals(root1.left, root2.left) && equals(root1.right, root2.right);
}