剑指offer有java吗_GitHub - ciryu/Sword-pointing-to-offer: 剑指offer java版实现

剑指offer JAVA解

公共类

BinaryTreeNode

public class BinaryTreeNode {

private int data;

private BinaryTreeNode LchildNode;

private BinaryTreeNode RchildNode;

public BinaryTreeNode(int data) {

super();

this.data = data;

}

public int getData() {

return data;

}

public void setData(int data) {

this.data = data;

}

public BinaryTreeNode getLchildNode() {

return LchildNode;

}

public void setLchildNode(BinaryTreeNode lchildNode) {

LchildNode = lchildNode;

}

public BinaryTreeNode getRchildNode() {

return RchildNode;

}

public void setRchildNode(BinaryTreeNode rchildNode) {

RchildNode = rchildNode;

}

}

Node

class Node {

String data;

Node next;

public Node(String data) {

super();

this.data = data;

}

public Node(String data, Node next) {

super();

this.data = data;

this.next = next;

}

public String getData() {

return data;

}

public void setData(String data) {

this.data = data;

}

public Node getNext() {

return next;

}

public void setNext(Node next) {

this.next = next;

}

}

题解

设计一个类,我们只能生成该类的一个实例。

// 饿汉式 线程安全

class A {

private static final A instance = new A();

private A() {

}

public static A getInstance() {

return instance;

}

}

// 懒汉式 线程安全写法

class B {

private static volatile B instance = null;

private B() {

}

public static B getInstance() {

if (instance == null) {

synchronized (B.class) {

if (instance == null)

instance = new B();

}

}

return instance;

}

}

// 静态内部类方式 线程安全

class C {

private C() {

}

public static C getInstance() {

return CHolder.INSTANCE;

}

private static class CHolder {

private static final C INSTANCE = new C();

}

}

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否函数该整数。

public class No03 {

public static void main(String[] args) {

int[][] arr = {{1, 2, 8, 9},

{2, 4, 9, 12},

{4, 7, 10, 13},

{6, 8, 11, 15}};

System.out.println(search(arr, 7));

}

private static boolean search(int[][] arr, int value) {

int a = arr[0].length;

int b = arr.length;

int i = 0;

int j = a - 1;

while (i <= b - 1 && j >= 0) {

if (arr[i][j] == value) {

return true;

}

if (arr[i][j] > value) {

j--;

} else {

i++;

}

}

return false;

}

}

请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入"We are happy",则输出"We%20are%20happy"

public class No04 {

public static void main(String[] args) {

String str = "We are happy";

char[] charArray = str.toCharArray();

System.out.println(change(charArray));

}

private static String change(char[] charArray) {

int n = charArray.length;

int count = 0;

for (int i = 0; i < charArray.length; i++) {

if (charArray[i] == ' ') {

count++;

}

}

if (count == 0) {

return null;

}

char[] temp = new char[n + 2 * count];

int j = n + 2 * count - 1;

int i = n - 1;

while (i >= 0) {

if (charArray[i] == ' ') {

temp[j] = '0';

temp[j - 1] = '2';

temp[j - 2] = '%';

j = j - 3;

} else {

temp[j] = charArray[i];

j--;

}

i--;

}

return new String(temp);

}

}

输入一个链表的头节点,从尾到头打印每个节点的值

public class No05 {

public static void main(String[] args) {

Node node1 = new Node("A");

Node node2 = new Node("B");

Node node3 = new Node("C");

Node node4 = new Node("D");

Node node5 = new Node("E");

node1.setNext(node2);

node2.setNext(node3);

node3.setNext(node4);

node4.setNext(node5);

Node newNode = reverse2(node1);

while (newNode != null) {

System.out.print(newNode.data + " ");

newNode = newNode.getNext();

}

}

private static Node reverse(Node head) {

if (head.next == null) {

return head;

}

Node reverseHead = reverse(head.getNext());

head.getNext().setNext(head);

head.setNext(null);

return reverseHead;

}

private static Node reverse2(Node head) {

Node pre = head;

Node cur = head.getNext();

Node temp;

while (cur != null) {

temp = cur.getNext();

cur.setNext(pre);

pre = cur;

cur = temp;

}

head.setNext(null);

return pre;

}

}

根据前序遍历和中序遍历建立树

public class No06 {

public static void main(String[] args) {

String preOrder = "12473568";

String midOrder = "47215386";

BiTree tree = new BiTree(preOrder, midOrder, preOrder.length());

tree.postRootTraverse(tree.root);

}

}

class BiTree {

TreeNode root;

public BiTree(String preOrder, String midOrder, int count) {

if (count <= 0) {

return;

}

char c = preOrder.charAt(0);

int i = 0;

for (; i < count; i++) {

if (midOrder.charAt(i) == c)

break;

}

root = new TreeNode(c);

root.setLchild(new BiTree(preOrder.substring(1, i + 1), midOrder.substring(0, i), i).root);

root.setRchild(new BiTree(preOrder.substring(i + 1), midOrder.substring(i + 1), count - i - 1).root);

}

public void postRootTraverse(TreeNode root) {

if (root != null) {

postRootTraverse(root.getLchild());

postRootTraverse(root.getRchild());

System.out.print(root.getData());

}

}

}

两个栈建立队列

import java.util.Stack;

public class No07 {

private Stack s1 = new Stack();

private Stack s2 = new Stack();

public void offer(Object x) {

s1.push(x);

}

public void poll() {

if (s1.size() == 0 && s2.size() == 0) {

try {

throw new Exception("empty queue");

} catch (Exception e) {

e.printStackTrace();

}

} else {

if (s2.size() != 0) {

System.out.println(s2.peek().toString());

s2.pop();

} else {

while (s1.size() > 0) {

s2.push(s1.pop());

}

System.out.println(s2.peek().toString());

s2.pop();

}

}

}

public static void main(String[] args) {

No07 queue = new No07();

queue.offer("a");

queue.offer("b");

queue.offer("c");

queue.poll();

queue.poll();

queue.poll();

queue.poll();

}

}

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

public class No08 {

public static void main(String[] args) {

int[] arr = {3, 4, 5, 1, 2};

System.out.println(findMin(arr));

}

public static int findMin(int[] arr) {

int left = 0;

int right = arr.length - 1;

if (arr[right] > arr[left]) {

try {

throw new Exception("非旋转数组");

} catch (Exception e) {

e.printStackTrace();

return -1;

}

}

while (left < right) {

int mid = (left + right) / 2;

//对于{1,0,1,1,1}之类的特殊处理

if (arr[mid] == arr[left] && arr[left] == arr[right]) {

return seachMin(arr, left, right);

}

if (right - left == 1)

break;

if (arr[mid] >= arr[left]) {

left = mid;

} else {

right = mid;

}

}

return arr[right];

}

private static int seachMin(int[] arr, int left, int right) {

int result = arr[left];

for (int i = left + 1; i <= right; ++i) {

if (arr[i] < result)

result = arr[i];

}

return result;

}

}

写一个函数,输入n,求斐波那契数列的第n项 (一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级台阶总共有多少种跳法)

public class No09 {

public static void main(String[] args) {

System.out.println(fibonacci(5));

System.out.println(getMethodNumber(10));

}

private static long fibonacci(int n) {

long[] a = {0, 1};

if (n < 2)

return a[n];

long fib1 = 0;

long fib2 = 1;

long fibN = 0;

for (int i = 2; i <= n; i++) {

fibN = fib1 + fib2;

fib1 = fib2;

fib2 = fibN;

}

return fibN;

}

private static int getMethodNumber(int n) {

if (n == 0)

return 0;

if (n == 1)

return 1;

if (n == 2)

return 2;

return getMethodNumber(n - 1) + getMethodNumber(n - 2);

}

}

请实现一个函数,输入一个整数,输出该二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。

public class No10 {

public static void main(String[] args) {

System.out.println(getNum(9));

}

public static int getNum(int n) {

int num = 0;

while (n != 0) {

num++;

n = (n - 1) & n;

}

return num;

}

}

实现函数double Power(double base,int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

public class No11 {

public static void main(String[] args) {

System.out.println(Power(2.0, 3));

}

public static double Power(double base, int exponent) {

if (exponent == 0)

return 1;

if (exponent == 1)

return base;

double result = Power(base, exponent >> 1);

result *= result;

if ((exponent & 0x1) == 1) {

result *= base;

}

return result;

}

}

输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。

public class No12 {

public static void main(String[] args) {

printNum(3);

}

private static void printNum(int n) {

if (n < 0)

return;

int[] array = new int[n];

printArray(array, 0);

}

private static void printArray(int[] array, int n) {

if (n != array.length) {

for (int i = 0; i < 10; i++) {

array[n] = i;

printArray(array, n + 1);

}

} else {

boolean flag = false;

for (int j = 0; j < array.length; j++) {

if (array[j] != 0) {

flag = true;

}

if (flag) {

System.out.print(array[j]);

}

}

// 去掉空白行

if (flag) {

System.out.println();

}

}

}

}

给定单向链表的头指针和一个结点指针, 定义一个函数在O(1)时间删除该节点

public class No13 {

public static void main(String[] args) {

Node a = new Node("A");

Node b = new Node("B");

Node c = new Node("C");

Node d = new Node("D");

a.setNext(b);

b.setNext(c);

c.setNext(d);

delete(a, d);

Node temp = a;

while (temp != null) {

System.out.println(temp.getData());

temp = temp.next;

}

}

private static void delete(Node head, Node c) {

// 如果是尾节点,只能遍历删除

if (c.next == null) {

while (head.next != c) {

head = head.next;

}

head.next = null;

} else if (head == c) {

head = null;

} else {

c.setData(c.getNext().getData());

c.setNext(c.getNext().getNext());

}

}

}

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

public class No14 {

public static void main(String[] args) {

int[] array = {3, 7, 4, 8, 23, 56, 77, 89, 46, 11, 66, 77};

mysort(array);

for (int a : array) {

System.out.println(" " + a);

}

}

private static void mysort(int[] array) {

if (array == null) {

return;

}

int left = 0;

int right = array.length - 1;

while (left < right) {

while (left < right && !isEven(array[left])) {

left++;

}

while (left < right && isEven(array[right])) {

right--;

}

if (left < right) {

int temp = array[right];

array[right] = array[left];

array[left] = temp;

}

if (left >= right) {

break;

}

}

}

private static boolean isEven(int i) {

return (i & 0x1) == 0;

}

}

输入一个链表,输出该链表中倒数第K个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1,2,3,4,5,6。这个链表的倒数第3个结点是值为4的结点。(注意代码鲁棒性,考虑输入空指针,链表结点总数少于k,输入的k参数为0)

public class No15 {

public static void main(String[] args) {

Node a = new Node("1");

Node b = new Node("2");

Node c = new Node("3");

Node d = new Node("4");

Node e = new Node("5");

Node f = new Node("6");

a.setNext(b);

b.setNext(c);

c.setNext(d);

d.setNext(e);

e.setNext(f);

System.out.print(FindDataFromTail(a, 5));

}

private static String FindDataFromTail(Node a, int k) {

if (a == null)

return null;

if (k == 0) {

System.out.println("k应该从1开始");

return null;

}

Node node1 = a;

Node node2 = null;

for (int i = 0; i < k - 1; i++) {

if (node1.getNext() == null) {

System.out.println("k不应该大于链表长度");

return null;

}

node1 = node1.getNext();

}

node2 = a;

while (node1.getNext() != null) {

node1 = node1.getNext();

node2 = node2.getNext();

}

return node2.getData();

}

}

15_2. 求链表的中间结点。如果链表中结点总数为奇数,返回中间结点;如果结点总数为偶数,返回中间两个结点的任意一个

public class No15_2 {

public static void main(String[] args) {

Node a = new Node("1");

Node b = new Node("2");

Node c = new Node("3");

Node d = new Node("4");

Node e = new Node("5");

Node f = new Node("6");

Node g = new Node("7");

a.setNext(b);

b.setNext(c);

c.setNext(d);

d.setNext(e);

e.setNext(f);

f.setNext(g);

Node mid = getMid(a);

System.out.println(mid.getData());

}

private static Node getMid(Node a) {

if (a == null) {

return null;

}

Node slow = a;

Node fast = a;

while (fast.getNext() != null && fast.getNext().getNext() != null) {

slow = slow.getNext();

fast = fast.getNext().getNext();

}

return slow;

}

}

同第5题

输入两个递增排序的链表,合并这两个链表并使新链表中结点仍然是按照递增排序的。例如输入1->3->5->7和2->4->6->8,则合并之后的升序链表应该是1->2->3->4->5->6->7->8 。

public class No17 {

public static void main(String[] args) {

Node node1 = new Node(1);

Node node2 = new Node(3);

Node node3 = new Node(5);

Node node4 = new Node(7);

node1.setNext(node2);

node2.setNext(node3);

node3.setNext(node4);

Node node5 = new Node(2);

Node node6 = new Node(4);

Node node7 = new Node(6);

node5.setNext(node6);

node6.setNext(node7);

Node head = merge(node1, node5);

while (head != null) {

System.out.print(head.getData() + " ");

head = head.getNext();

}

}

private static Node merge(Node a, Node b) {

if (a == null && b == null)

return null;

if (a == null)

return b;

if (b == null)

return a;

Node head = a.getData() > b.getData() ? b : a;

Node index1 = head.getNext();

Node index2 = head == a ? b : a;

while (index1 != null && index2 != null) {

if (index1.getData() < index2.getData()) {

head.setNext(index1);

index1 = index1.getNext();

} else {

head.setNext(index2);

index2 = index2.getNext();

}

head = head.getNext();

}

if (index1 == null) {

while (index2 != null) {

head.setNext(index2);

index2 = index2.getNext();

head = head.getNext();

}

} else {

while (index1 != null) {

head.setNext(index1);

index1 = index1.getNext();

head = head.getNext();

}

}

return a.getData() > b.getData() ? b : a;

}

}

输入两颗二叉树A和B,判断B是不是A的子结构

public class No18 {

public static void main(String[] args) {

BinaryTreeNode node1 = new BinaryTreeNode(8);

BinaryTreeNode node2 = new BinaryTreeNode(8);

BinaryTreeNode node3 = new BinaryTreeNode(7);

BinaryTreeNode node4 = new BinaryTreeNode(9);

BinaryTreeNode node5 = new BinaryTreeNode(2);

BinaryTreeNode node6 = new BinaryTreeNode(4);

BinaryTreeNode node7 = new BinaryTreeNode(7);

node1.setLchildNode(node2);

node1.setRchildNode(node3);

node2.setLchildNode(node4);

node2.setRchildNode(node5);

node5.setLchildNode(node6);

node5.setRchildNode(node7);

BinaryTreeNode a = new BinaryTreeNode(8);

BinaryTreeNode b = new BinaryTreeNode(9);

BinaryTreeNode c = new BinaryTreeNode(2);

a.setLchildNode(b);

a.setRchildNode(c);

System.out.println(hasSubTree(node1, a));

}

private static boolean hasSubTree(BinaryTreeNode root1, BinaryTreeNode root2) {

boolean result = false;

if (root1 != null && root2 != null) {

if (root1.getData() == root2.getData()) {

result = doseTree1HaveTree2(root1, root2);

if (!result) {

result = hasSubTree(root1.getLchildNode(), root2);

}

if (!result)

result = hasSubTree(root1.getRchildNode(), root2);

}

}

return result;

}

private static boolean doseTree1HaveTree2(BinaryTreeNode root1,

BinaryTreeNode root2) {

if (root2 == null)

return true;

if (root1 == null)

return false;

if (root1.getData() != root2.getData()) {

return false;

}

return doseTree1HaveTree2(root1.getLchildNode(), root2.getLchildNode())

&& doseTree1HaveTree2(root1.getRchildNode(), root2.getRchildNode());

}

}

请完成一个函数,输入一个二叉树,该函数输出它的镜像

public class No19 {

public static void main(String[] args) {

BinaryTreeNode node1 = new BinaryTreeNode(8);

BinaryTreeNode node2 = new BinaryTreeNode(6);

BinaryTreeNode node3 = new BinaryTreeNode(10);

BinaryTreeNode node4 = new BinaryTreeNode(5);

BinaryTreeNode node5 = new BinaryTreeNode(7);

BinaryTreeNode node6 = new BinaryTreeNode(9);

BinaryTreeNode node7 = new BinaryTreeNode(11);

node1.setLchildNode(node2);

node1.setRchildNode(node3);

node2.setLchildNode(node4);

node2.setRchildNode(node5);

node3.setLchildNode(node6);

node3.setRchildNode(node7);

mirror(node1);

print(node1);

}

private static void print(BinaryTreeNode root) {

if (root != null) {

System.out.println(root.getData());

print(root.getLchildNode());

print(root.getRchildNode());

}

}

private static void mirror(BinaryTreeNode root) {

if (root == null) {

return;

}

if (root.getLchildNode() == null && root.getRchildNode() == null) {

return;

}

BinaryTreeNode temp = root.getLchildNode();

root.setLchildNode(root.getRchildNode());

root.setRchildNode(temp);

mirror(root.getLchildNode());

mirror(root.getRchildNode());

}

}

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字

public class No20 {

public static void main(String[] args) {

int[][] a = create(5, 5);

print(a);

clockWisePrint(a, 0, 4);

}

private static void clockWisePrint(int[][] a, int i, int j) {

if (j < i)

return;

if (j == i) {

System.out.print(a[i][j] + " ");

return;

}

int y = i;

while (y <= j) {

System.out.print(a[i][y] + " ");

y++;

}

y = i + 1;

while (y <= j) {

System.out.print(a[y][j] + " ");

y++;

}

y = j - 1;

while (y >= i) {

System.out.print(a[j][y] + " ");

y--;

}

y = j - 1;

while (y >= i + 1) {

System.out.print(a[y][i] + " ");

y--;

}

clockWisePrint(a, i + 1, j - 1);

}

private static void print(int[][] a) {

for (int i = 0; i < a.length; i++) {

for (int j = 0; j < a[i].length; j++) {

System.out.print(a[i][j] + " ");

}

System.out.println();

}

}

public static int[][] create(int row, int line) {

int[][] a = new int[row][line];

int num = 1;

for (int i = 0; i < row; i++) {

for (int j = 0; j < line; j++) {

a[i][j] = num++;

}

}

return a;

}

}

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push以及pop的时间复杂度都是O(1)。

import java.util.Stack;

public class No21 {

public static void main(String[] args) {

MyStack a = new MyStack();

System.out.println(a.min());

a.push(10);

a.push(11);

System.out.println(a.min());

}

}

class MyStack {

private Stack stack1, stackHelp;

public MyStack() {

stack1 = new Stack();

stackHelp = new Stack();

}

public void push(int num) {

stack1.push(num);

if (stackHelp.size() == 0 || num < stackHelp.peek()) {

stackHelp.push(num);

} else {

stackHelp.push(stackHelp.peek());

}

}

public void pop() {

stack1.pop();

stackHelp.pop();

}

public Integer min() {

if (stackHelp.size() == 0) {

return null;

}

return stackHelp.peek();

}

}

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该压栈序列的弹出序列。

import java.util.Stack;

public class No22 {

public static void main(String[] args) {

Integer[] pushOrder = {1, 2, 3, 4, 5};

Integer[] popOrder = {4, 5, 3, 1, 2};

System.out.println(isRight(pushOrder, popOrder));

}

private static boolean isRight(Integer[] pushOrder, Integer[] popOrder) {

Stack stack = new Stack();

int pushIndex = 0;

for (int i = 0; i < popOrder.length; i++) {

if (!stack.isEmpty() && stack.peek() == popOrder[i])

stack.pop();

else {

while (pushIndex <= pushOrder.length - 1 && pushOrder[pushIndex] != popOrder[i]) {

stack.push(pushOrder[pushIndex++]);

}

if (pushIndex > pushOrder.length - 1) {

return false;

} else {

pushIndex++;

}

}

}

return true;

}

}

从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印

import java.util.LinkedList;

import java.util.Queue;

public class No23 {

public static void main(String[] args) {

BinaryTreeNode node1 = new BinaryTreeNode(8);

BinaryTreeNode node2 = new BinaryTreeNode(6);

BinaryTreeNode node3 = new BinaryTreeNode(10);

BinaryTreeNode node4 = new BinaryTreeNode(5);

BinaryTreeNode node5 = new BinaryTreeNode(7);

BinaryTreeNode node6 = new BinaryTreeNode(9);

BinaryTreeNode node7 = new BinaryTreeNode(11);

node1.setLchildNode(node2);

node1.setRchildNode(node3);

node2.setLchildNode(node4);

node2.setRchildNode(node5);

node3.setLchildNode(node6);

node3.setRchildNode(node7);

printFromTopToBottom(node1);

}

private static void printFromTopToBottom(BinaryTreeNode root) {

if (root == null)

return;

Queue queue = new LinkedList();

queue.add(root);

while (!queue.isEmpty()) {

BinaryTreeNode node = queue.poll();

System.out.println(node.getData());

if (node.getLchildNode() != null) {

queue.add(node.getLchildNode());

}

if (node.getRchildNode() != null) {

queue.add(node.getRchildNode());

}

}

}

}

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。

public class No24 {

public static void main(String[] args) {

int[] array = {5, 7, 6, 9, 11, 10, 8};

// int[] array={7,4,6,5};

boolean b = verfiySequenceOfBST(array, 0, 6);

System.out.println(b);

}

private static boolean verfiySequenceOfBST(int[] array, int start, int end) {

if (array == null || start > end || start < 0 || end < 0)

return false;

if (start == end)

return true;

int root = array[end];

int i = start;

for (; i <= end; i++) {

if (array[i] > root)

break;

}

int j = i;

for (; j <= end; j++) {

if (array[j] < root)

return false;

}

boolean left = true;

if (i > start) {

left = verfiySequenceOfBST(array, start, i - 1);

}

boolean right = true;

if (i < end) {

right = verfiySequenceOfBST(array, i, end - 1);

}

return (left && right);

}

}

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

import java.util.Stack;

public class No25 {

public static void main(String[] args) {

BinaryTreeNode root = new BinaryTreeNode(10);

BinaryTreeNode node1 = new BinaryTreeNode(5);

BinaryTreeNode node2 = new BinaryTreeNode(4);

BinaryTreeNode node3 = new BinaryTreeNode(7);

BinaryTreeNode node4 = new BinaryTreeNode(12);

root.setLchildNode(node1);

root.setRchildNode(node4);

node1.setLchildNode(node2);

node1.setRchildNode(node3);

findPath(root, 22);

}

private static void findPath(BinaryTreeNode root, int i) {

if (root == null)

return;

Stack stack = new Stack();

int currentSum = 0;

findPath(root, i, stack, currentSum);

}

private static void findPath(BinaryTreeNode root, int i,

Stack stack, int currentSum) {

currentSum += root.getData();

stack.push(root.getData());

if (root.getLchildNode() == null && root.getRchildNode() == null) {

if (currentSum == i) {

System.out.println("找到路径");

for (int path : stack) {

System.out.println(path + " ");

}

}

}

if (root.getLchildNode() != null) {

findPath(root.getLchildNode(), i, stack, currentSum);

}

if (root.getRchildNode() != null) {

findPath(root.getRchildNode(), i, stack, currentSum);

}

stack.pop();

}

}

请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。

public class No26 {

public static void main(String[] args) {

ComplexListNode node1 = new ComplexListNode(1);

ComplexListNode node2 = new ComplexListNode(2);

ComplexListNode node3 = new ComplexListNode(3);

ComplexListNode node4 = new ComplexListNode(4);

ComplexListNode node5 = new ComplexListNode(5);

node1.next = node2;

node2.next = node3;

node3.next = node4;

node4.next = node5;

node1.sibling = node3;

node2.sibling = node5;

node4.sibling = node2;

ComplexListNode result = clone(node1);

while (result != null) {

System.out.println(result.data);

result = result.next;

}

}

private static ComplexListNode clone(ComplexListNode head) {

cloneNodes(head);

copySibingNodes(head);

return separateNodes(head);

}

private static ComplexListNode separateNodes(ComplexListNode head) {

ComplexListNode node = head;

ComplexListNode cloneHead = null;

ComplexListNode cloneNode = null;

if (node != null) {

cloneNode = node.next;

cloneHead = cloneNode;

node.next = cloneNode.next;

node = node.next;

}

while (node != null) {

cloneNode.next = node.next;

cloneNode = cloneNode.next;

node.next = cloneNode.next;

node = node.next;

}

return cloneHead;

}

private static void copySibingNodes(ComplexListNode head) {

ComplexListNode node = head;

while (node != null) {

ComplexListNode cloneNode = node.next;

if (node.sibling != null) {

cloneNode.sibling = node.sibling.next;

}

node = cloneNode.next;

}

}

private static void cloneNodes(ComplexListNode head) {

ComplexListNode node = head;

while (node != null) {

ComplexListNode cloneNode = new ComplexListNode(node.data);

cloneNode.next = node.next;

node.next = cloneNode;

node = cloneNode.next;

}

}

}

class ComplexListNode {

int data;

ComplexListNode next;

ComplexListNode sibling;

public ComplexListNode(int data) {

super();

this.data = data;

}

}

输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

public class No27 {

public static void main(String[] args) {

BinaryTreeNode root = new BinaryTreeNode(10);

BinaryTreeNode node1 = new BinaryTreeNode(6);

BinaryTreeNode node2 = new BinaryTreeNode(14);

BinaryTreeNode node3 = new BinaryTreeNode(4);

BinaryTreeNode node4 = new BinaryTreeNode(8);

BinaryTreeNode node5 = new BinaryTreeNode(12);

BinaryTreeNode node6 = new BinaryTreeNode(16);

root.setLchildNode(node1);

root.setRchildNode(node2);

node1.setLchildNode(node3);

node1.setRchildNode(node4);

node2.setLchildNode(node5);

node2.setRchildNode(node6);

BinaryTreeNode head = covert(root);

while (head != null) {

System.out.println(head.getData());

head = head.getRchildNode();

}

}

private static BinaryTreeNode covert(BinaryTreeNode root) {

BinaryTreeNode lastNodeList = null;

lastNodeList = convertNode(root, lastNodeList);

while (lastNodeList != null && lastNodeList.getLchildNode() != null) {

lastNodeList = lastNodeList.getLchildNode();

}

return lastNodeList;

}

private static BinaryTreeNode convertNode(BinaryTreeNode root,

BinaryTreeNode lastNodeList) {

if (root == null)

return null;

BinaryTreeNode current = root;

if (current.getLchildNode() != null) {

lastNodeList = convertNode(current.getLchildNode(), lastNodeList);

}

current.setLchildNode(lastNodeList);

if (lastNodeList != null) {

lastNodeList.setRchildNode(current);

}

lastNodeList = current;

if (current.getRchildNode() != null) {

lastNodeList = convertNode(current.getRchildNode(), lastNodeList);

}

return lastNodeList;

}

}

输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc, 则打印出由字符串a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba

public class No28 {

public static void main(String[] args) {

myPrint("abc");

}

private static void myPrint(String str) {

if (str == null)

return;

char[] chs = str.toCharArray();

myPrint(chs, 0);

}

private static void myPrint(char[] str, int i) {

if (i >= str.length)

return;

if (i == str.length - 1) {

System.out.println(String.valueOf(str));

} else {

for (int j = i; j < str.length; j++) {

char temp = str[j];

str[j] = str[i];

str[i] = temp;

myPrint(str, i + 1);

temp = str[j];

str[j] = str[i];

str[i] = temp;

}

}

}

}

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2},由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

public class No29 {

public static void main(String[] args) {

int[] arr = {1, 2, 3, 2, 2, 2, 5, 4, 2};

System.out.println(findNum(arr));

}

private static Integer findNum(int[] arr) {

if (arr == null)

return null;

int result = arr[0];

int count = 1;

for (int i = 1; i < arr.length; i++) {

if (count == 0) {

result = arr[i];

count = 1;

} else if (arr[i] == result) {

count++;

} else {

count--;

}

}

return result;

}

}

题目:输入n个整数,输出其中最小的k个。例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

public class TopK {

public static void main(String[] args) {

int[] arr = {1, 3, 4, 2, 7, 8, 9, 10, 14, 16};

System.out.println(minK(arr, 1));

System.out.println(minK(arr, 2));

System.out.println(minK(arr, 3));

System.out.println(minK(arr, 4));

System.out.println(minK(arr, 5));

System.out.println(minK(arr, 6));

}

public static int minK(int[] arr, int k) {

return minK(arr, k, 0, arr.length - 1);

}

public static int minK(int[] arr, int k, int start, int end) {

int mid = partition(arr, start, end);

if (mid - start == k - 1) {

return arr[mid];

} else if (mid - start > k - 1) {

return minK(arr, k, start, mid - 1);

} else {

return minK(arr, k - 1 - (mid - start), mid + 1, end);

}

}

public static int partition(int[] arr, int start, int end) {

int key = arr[start];

int keyIndex = start;

start++;

for (int i = start; i <= end; i++) {

if (arr[i] < key) {

swap(arr, i, start);

start++;

}

}

swap(arr, keyIndex, start - 1);

return start - 1;

}

public static void swap(int[] arr, int i, int j) {

int temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

}

}

输入一个整型数组,数组里有正数,也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)

public class No31 {

public static void main(String[] args) {

int[] arr = {1, -2, 3, 10, -4, 7, 2, -5};

System.out.println(maxSub(arr));

}

private static int maxSub(int[] arr) {

int max = 0;

int n = arr.length;

int sum = 0;

for (int i = 0; i < n; i++) {

sum += arr[i];

if (sum > max)

max = sum;

else if (sum < 0)

sum = 0;

}

return max;

}

}

输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现5次。

public class No32 {

public static void main(String[] args) {

System.out.println(countOne(115));

}

private static long countOne(int n) {

long count = 0;

long i = 1;

long current = 0, after = 0, before = 0;

while ((n / i) != 0) {

current = (n / i) % 10;

before = n / (i * 10);

after = n - (n / i) * i;

if (current > 1)

count = count + (before + 1) * i;

else if (current == 0)

count = count + before * i;

else if (current == 1)

count = count + before * i + after + 1;

i = i * 10;

}

return count;

}

}

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出所有数字中最小的一个。例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323

public class No33 {

public static void main(String[] args) {

int[] array = {321, 32, 3};

printMin(array);

}

private static void printMin(int[] array) {

int[] clone = array.clone();

printMin(clone, 0, clone.length - 1);

for (int i : clone)

System.out.print(i);

}

private static void printMin(int[] array, int start, int end) {

if (start < end) {

int main_number = array[end];

int small_cur = start;

for (int j = start; j < end; j++) {

if (isSmall(String.valueOf(array[j]), String.valueOf(main_number))) {

int temp = array[j];

array[j] = array[small_cur];

array[small_cur] = temp;

small_cur++;

}

}

array[end] = array[small_cur];

array[small_cur] = main_number;

printMin(array, 0, small_cur - 1);

printMin(array, small_cur + 1, end);

}

}

public static boolean isSmall(String m, String n) {

String left = m + n;

String right = n + m;

boolean result = false;

for (int i = 0; i < left.length(); i++) {

if (left.charAt(i) < right.charAt(i))

return true;

else if (left.charAt(i) > right.charAt(i))

return false;

}

return result;

}

}

我们把只包含因子2,3和5的数称作丑数。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一个丑数。

public class No34 {

public static void main(String[] args) {

System.out.println(getUgly(20));

}

private static int getUgly(int n) {

if (n < 0)

return 0;

int[] uglyArray = new int[n];

uglyArray[0] = 1;

int multiply2 = 0;

int multiply3 = 0;

int multiply5 = 0;

for (int i = 1; i < n; i++) {

int min = getMin(uglyArray[multiply2] * 2, uglyArray[multiply3] * 3, uglyArray[multiply5] * 5);

uglyArray[i] = min;

System.out.println(uglyArray[i]);

while (uglyArray[multiply2] * 2 == uglyArray[i])

multiply2++;

while (uglyArray[multiply3] * 3 == uglyArray[i])

multiply3++;

while (uglyArray[multiply5] * 5 == uglyArray[i])

multiply5++;

}

return uglyArray[n - 1];

}

private static int getMin(int i, int j, int k) {

int min = (i < j) ? i : j;

return (min < k) ? min : k;

}

}

在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出'b'

import java.util.LinkedHashMap;

public class No35 {

public static void main(String[] args) {

System.out.println(firstOnceNumber("abaccdeff"));

}

private static Character firstOnceNumber(String str) {

if (str == null)

return null;

char[] strChar = str.toCharArray();

LinkedHashMap hash = new LinkedHashMap();

for (char item : strChar) {

if (hash.containsKey(item))

hash.put(item, hash.get(item) + 1);

else

hash.put(item, 1);

}

for (char key : hash.keySet()) {

if (hash.get(key) == 1) {

return key;

}

}

return null;

}

}

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

public class No36 {

public static void main(String[] args) {

int[] arr = {7, 5, 6, 4};

System.out.println(getInversePairs(arr));

}

private static int getInversePairs(int[] arr) {

if (arr == null)

return 0;

int[] clone = arr.clone();

return mergeSort(arr, clone, 0, arr.length - 1);

}

private static int mergeSort(int[] array, int[] result, int start, int end) {

if (start == end) {

result[start] = array[start];

return 0;

}

int length = (end - start) / 2;

int left = mergeSort(result, array, start, start + length);

int right = mergeSort(result, array, start + length + 1, end);

int leftIndex = start + length;

int rightIndex = end;

int count = 0;

int point = rightIndex;

while (leftIndex >= start && rightIndex >= start + length + 1) {

if (array[leftIndex] > array[rightIndex]) {

result[point--] = array[leftIndex--];

count += rightIndex - start - length;

} else {

result[point--] = array[rightIndex--];

}

}

for (int i = leftIndex; i >= start; i--)

result[point--] = array[i];

for (int j = rightIndex; j >= start + length + 1; j--)

result[point--] = array[j];

return left + right + count;

}

}

输入两个单向链表,找出它们的第一个公共结点。

public class No37 {

public static void main(String[] args) {

ListNode head1 = new ListNode();

ListNode second1 = new ListNode();

ListNode third1 = new ListNode();

ListNode forth1 = new ListNode();

ListNode fifth1 = new ListNode();

ListNode head2 = new ListNode();

ListNode second2 = new ListNode();

ListNode third2 = new ListNode();

ListNode forth2 = new ListNode();

head1.nextNode = second1;

second1.nextNode = third1;

third1.nextNode = forth1;

forth1.nextNode = fifth1;

head2.nextNode = second2;

second2.nextNode = forth1;

third2.nextNode = fifth1;

head1.data = 1;

second1.data = 2;

third1.data = 3;

forth1.data = 6;

fifth1.data = 7;

head2.data = 4;

second2.data = 5;

third2.data = 6;

forth2.data = 7;

System.out.println(findFirstCommonNode(head1, head2).data);

}

public static ListNode findFirstCommonNode(ListNode head1, ListNode head2) {

int len1 = getListLength(head1);

int len2 = getListLength(head2);

ListNode longListNode = null;

ListNode shortListNode = null;

int dif = 0;

if (len1 > len2) {

longListNode = head1;

shortListNode = head2;

dif = len1 - len2;

} else {

longListNode = head2;

shortListNode = head1;

dif = len2 - len1;

}

for (int i = 0; i < dif; i++) {

longListNode = longListNode.nextNode;

}

while (longListNode != null && shortListNode != null

&& longListNode != shortListNode) {

longListNode = longListNode.nextNode;

shortListNode = shortListNode.nextNode;

}

return longListNode;

}

private static int getListLength(ListNode head1) {

int result = 0;

if (head1 == null)

return result;

ListNode point = head1;

while (point != null) {

point = point.nextNode;

result++;

}

return result;

}

}

class ListNode {

int data;

ListNode nextNode;

}

统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。

public class No38 {

public static void main(String[] args) {

int[] array = {1, 2, 3, 3, 3, 3, 4, 5};

System.out.println(getNumberOfK(array, 3));

}

private static int getNumberOfK(int[] array, int k) {

int num = 0;

if (array != null) {

int first = getFirstK(array, k, 0, array.length - 1);

int last = getLastK(array, k, 0, array.length - 1);

//System.out.println(last);

if (first > -1 && last > -1)

num = last - first + 1;

}

return num;

}

private static int getLastK(int[] array, int k, int start, int end) {

if (start > end)

return -1;

int mid = (start + end) / 2;

int midData = array[mid];

if (midData == k) {

if ((mid < array.length - 1 && array[mid + 1] != k) || mid == array.length - 1) {

return mid;

} else {

start = mid + 1;

}

} else if (midData < k)

start = mid + 1;

else

end = mid - 1;

return getLastK(array, k, start, end);

}

private static int getFirstK(int[] array, int k, int start, int end) {

if (start > end)

return -1;

int mid = (start + end) / 2;

int midData = array[mid];

if (midData == k) {

if ((mid > 0 && array[mid - 1] != k) || mid == 0) {

return mid;

} else {

end = mid - 1;

}

} else if (midData > k)

end = mid - 1;

else

start = mid + 1;

return getFirstK(array, k, start, end);

}

}

输入一颗二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

public class No39 {

public int treeDepth(BinaryTreeNode root) {

if (root == null) return 0;

int left = treeDepth(root.getLchildNode());

int right = treeDepth(root.getRchildNode());

return (left > right) ? left + 1 : right + 1;

}

}

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度O(1)

public class No40 {

public static void main(String[] args) {

int[] array = {2, 4, 3, 6, 3, 2, 5, 5};

findNumsAppearOnce(array);

}

private static void findNumsAppearOnce(int[] array) {

if (array == null)

return;

int num = 0;

for (int i : array) {

num ^= i;

}

int index = findFirstBitIs1(num);

int number1 = 0;

int number2 = 0;

for (int i : array) {

if (isBit1(i, index))

number1 ^= i;

else

number2 ^= i;

}

System.out.println(number1);

System.out.println(number2);

}

private static boolean isBit1(int number, int index) {

number = number >> index;

return (number & 1) == 0;

}

private static int findFirstBitIs1(int num) {

int index = 0;

while ((num & 1) == 0) {

num = num >> 1;

index++;

}

return index;

}

}

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。

public class No41 {

public static void main(String[] args) {

int[] data = {1, 2, 4, 7, 11, 15};

System.out.println(findNumberWithSum(data, 15));

}

private static boolean findNumberWithSum(int[] data, int sum) {

boolean found = false;

if (data == null)

return found;

int num1 = 0;

int num2 = 0;

int start = 0;

int end = data.length - 1;

while (start < end) {

int curSum = data[start] + data[end];

if (curSum == sum) {

num1 = data[start];

num2 = data[end];

found = true;

break;

} else if (curSum > sum)

end--;

else

start++;

}

System.out.println(num1);

System.out.println(num2);

return found;

}

}

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am student.",则输出"student. a am I"。

public class No42 {

public static void main(String[] args) {

String string = "I am a student.";

reverseSentence(string);

}

private static void reverseSentence(String str) {

if (str == null)

return;

char[] arr = str.toCharArray();

reverse(arr, 0, arr.length - 1);

int start = 0;

int end = 0;

for (char i = 0; i < arr.length; i++) {

if (arr[i] == ' ') {

reverse(arr, start, end);

end++;

start = end;

} else if (i == arr.length) {

end++;

reverse(arr, start, end);

} else {

end++;

}

}

for (char c : arr) {

System.out.print(c);

}

}

private static void reverse(char[] arr, int start, int end) {

for (int i = start, j = end; i <= j; i++, j--) {

char temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

}

}

}

把n个骰子仍在地上,所有骰子朝上一面的点数之和为s,输入n,打印出s的所有可能的值出现的概率

public class No43 {

public static void main(String[] args) {

printProbability(2);

}

private static void printProbability(int num) {

if (num < 1)

return;

int gMaxValue = 6;

int[][] probabilities = new int[2][];

probabilities[0] = new int[gMaxValue * num + 1];

probabilities[1] = new int[gMaxValue * num + 1];

int flag = 0;

for (int i = 1; i <= gMaxValue; i++) {

probabilities[flag][i] = 1;

}

for (int k = 2; k <= num; k++) {

for (int i = 0; i < k; i++) {

probabilities[1 - flag][i] = 0;

}

for (int i = k; i <= gMaxValue * k; i++) {

probabilities[1 - flag][i] = 0;

for (int j = 1; j <= i && j <= gMaxValue; j++)

probabilities[1 - flag][i] += probabilities[flag][i - j];

}

flag = 1 - flag;

}

double total = Math.pow(gMaxValue, num);

for (int i = num; i <= gMaxValue * num; i++) {

double ratio = (double) probabilities[flag][i] / total;

System.out.print(i + " ");

System.out.println(ratio);

}

}

}

44.从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。

import java.util.Arrays;

public class No44 {

public static void main(String[] args) {

int[] array = {0, 4, 6, 8, 0};

System.out.println(isContinuous(array));

}

private static boolean isContinuous(int[] arr) {

if (arr == null || arr.length != 5)

return false;

Arrays.sort(arr);

int numberZero = 0;

int numberGap = 0;

for (int i = 0; i < arr.length && arr[i] == 0; i++)

numberZero++;

int small = numberZero;

int big = small + 1;

while (big < arr.length) {

if (arr[small] == arr[big])

return false;

numberGap += arr[big] - arr[small] - 1;

small = big;

big++;

}

return numberGap <= numberZero;

}

}

0~n-1这n个数字排列成一个圆圈,从数字0开始每次从这个圆圈中删除第m个数字。求出这个圆圈里剩下的最后一个数字。

public class No45 {

public static void main(String[] args) {

System.out.println(lastRemaining(6, 3));

}

public static int lastRemaining(int n, int m) {

if (n < 1 || m < 1)

return -1;

int last = 0;

for (int i = 2; i <= n; i++) {

last = (last + m) % i;

}

return last;

}

}

写一个函数,求两个整数之和,要求函数体内部不能使用"+"、"-"、"*"、""。

public class No47 {

public static void main(String[] args) {

System.out.println(add(5, 8));

}

private static int add(int num1, int num2) {

int sum, carry;

do {

sum = num1 ^ num2;

carry = (num1 & num2) << 1;

num1 = sum;

num2 = carry;

} while (num2 != 0);

return num1;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值