剑指offer题解02-10
02 单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
从具体实现角度来说,主要有三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
// 懒汉式-线程不安全
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
// 双重校验锁-线程安全
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
// 静态内部类实现
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}
03 数组中重复的数字
/**
* 03 数组中重复的数字
* 在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道 有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
*/
public class _03 {
public static boolean duplicate(int[] numbers,int length,int[] duplication) {
int [] array = new int[length];
for (int i = 0; i < length; ++i) {
if (array[numbers[i]] == 0) {
array[numbers[i]] = 1;
} else {
duplication[0] =numbers[i];
return true;
}
}
return false;
}
public static void main(String[] args) {
int[] numbers = {2, 3, 1, 0, 2, 5, 3};
int[] duplication = new int[1];
System.out.println(duplicate(numbers, numbers.length, duplication) + " " + duplication[0]);
}
}
04 二维数组中的查找
/**
* 04 二维数组中的查找
* 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
*/
public class _04 {
public static boolean find(int target, int [][] array) {
if (array == null || array.length == 0) {
return false;
}
if (array[0].length == 0) {
return false;
}
int col = array[0].length;
int row = array.length;
int i = row - 1;
int j = 0;
while (j < col && i >= 0) {
if (array[i][j] == target) {
return true;
} else if (array[i][j] > target) {
i--;
} else {
j++;
}
}
return false;
}
public static void main(String[] args) {
int[][] array = {{1, 4, 7, 11, 15},
{2, 5, 8, 12, 19}};
System.out.println("Find(5, array) = " + find(5, array));
}
}
05 替换空格
/**
* 05 替换空格
* 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过 替换之后的字符串为We%20Are%20Happy。
*
* 在字符串尾部填充任意字符,使得字符串的长度等于替换之后的长度。因为一个空格要替换成三个字符 (%20),因此当遍历到一个空格时,需要在尾部填充两个任意字符。
* 令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2 从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。
* 从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容
*/
public class _05 {
public static String replaceSpace(StringBuffer str) {
int originalLength = str.length();
for (int i = 0; i < originalLength; ++i) {
if (str.charAt(i) == ' ') {
// 每遇到一个空格扩充2个长度
str.append(" ");
}
}
int newLength = str.length();
int j = newLength - 1;
for (int i = originalLength - 1; i >= 0; --i) {
if (str.charAt(i) == ' ') {
str.setCharAt(j--, '0');
str.setCharAt(j--, '2');
str.setCharAt(j--, '%');
} else {
str.setCharAt(j--, str.charAt(i));
}
}
return str.toString();
}
public static void main(String[] args) {
replaceSpace(new StringBuffer("We Are Happy"));
}
}
06 从头到尾打印链表
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 06 从头到尾打印链表
* 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
*/
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
public class _06 {
/**
* 使用堆栈
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
Stack<Integer> stack = new Stack<>();
ArrayList<Integer> arrayList = new ArrayList<>();
while (listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
while (!stack.empty()) {
arrayList.add(stack.pop());
}
return arrayList;
}
/**
* 使用递归
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead1(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
ArrayList<Integer> arrayList = printListFromTailToHead1(listNode.next);
arrayList.add(listNode.val);
return arrayList;
}
/**
* 使用头插法
* 构建一个头指针head,初始head->next = null,然后不断将listNode中的节点加到head后 面,相当于反向链表
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead2(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
// 头指针
ListNode head = new ListNode(0);
head.next = null;
// 将listNode中的结点逐步加到head后面
while (listNode != null) {
// 先存储下一个结点
ListNode nextNode = listNode.next;
// 头插
listNode.next = head.next;
head.next = listNode;
// 继续下一次循环
listNode = nextNode;
}
ArrayList<Integer> arrayList = new ArrayList<>();
// 头结点
listNode = head.next;
while (listNode != null) {
arrayList.add(listNode.val);
listNode = listNode.next;
}
return arrayList;
}
public static void main(String[] args) {
// 构造一个链表
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(2);
listNode2.next = null;
listNode1.next = listNode2;
List<Integer> list = printListFromTailToHead2(listNode1);
for (Integer integer : list) {
System.out.println(integer + " ");
}
}
/**
* 内部类:相当于一个链表节点
*/
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
}
07 重建二叉树
/**
* 07 重建二叉树
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结 果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并返回。
* 前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序 遍历结果,右部分为树的右子树中序遍历的结果,然后就可以接着分别对左右子树递归下去。
*/
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class _07 {
/**
* 重建二叉树
* @param pre 前序遍历
* @param in 中序遍历
* @return 返回重建的二叉树
*/
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || in == null || pre.length == 0 || in.length == 0) {
return null;
}
return reConstructBinaryTree(pre, in, 0, pre.length - 1, 0, in.length - 1);
}
/**
* 扩充前序与中序的索引参数,便于递归重建二叉树
* @param pre 前序遍历
* @param in 中序遍历
* @param preStart 前序遍历数组的开始索引
* @param preEnd 前序遍历数组的结束索引
* @param inStart 中序遍历数组的开始索引
* @param inEnd 中序遍历数组的结束索引
* @return 返回重建的二叉树
*/
private static TreeNode reConstructBinaryTree(int [] pre,int [] in, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd) {
return null;
}
// 根节点的值是前序遍历的第一个值
int rootValue = pre[preStart];
TreeNode treeNode = new TreeNode(rootValue);
// 找到中序遍历序列中的根节点的位置,递归得到左右节点
for (int i = inStart; i <= inEnd; ++i) {
if (in[i] == pre[preStart]) {
treeNode.left = reConstructBinaryTree(pre, in, preStart + 1, preStart + i - inStart, inStart, i - 1);
treeNode.right = reConstructBinaryTree(pre, in, preStart + i - inStart + 1, preEnd, i + 1, inEnd);
break;
}
}
return treeNode;
}
public static void main(String[] args) {
int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
reConstructBinaryTree(pre, in);
}
/**
* 内部类:二叉树结构
*/
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
08 二叉树的下一个结点
/**
* 08 二叉树的下一个结点
* 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不 仅包含左右子结点,同时包含指向父结点的指针
* 分三种情况:
* (1)当前节点有右子树,则下一个中序遍历节点是右子树中的最左节点
* (2)当前节点没有右子树,且该节点是其父节点的左节点,则下一个节点是其父节点
* (3)当前节点没有右子树,且该节点是其父节点的右节点,则沿着其父节点向上遍历,直到找到一个 是其父节点的左节点的节点,这个节点的父节点即为所求
*/
/**
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class _08 {
public static TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode == null) {
return null;
}
// 当前节点有右子树
if (pNode.right != null) {
pNode = pNode.right;
while (pNode.left != null) {
pNode = pNode.left;
}
return pNode;
}
// 当前节点没有右子树,且该节点没有父节点,是根节点
if (pNode.next == null) {
return null;
}
// 当前节点没有右子树,且该节点是其父节点的左节点
if (pNode.next.left == pNode) {
return pNode.next;
}
// 当前节点没有右子树,且该节点是其父节点的右节点
if (pNode.next.right == pNode) {
pNode = pNode.next;
while (pNode.next != null) {
if (pNode.next.left != pNode) {
pNode = pNode.next;
} else {
return pNode.next;
}
}
}
return null;
}
/**
* 二叉树结构,包含了指向其父节点的指针
*/
public static class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
}
09 用两个栈实现队列
import java.util.Stack;
/**
* 09 用两个栈实现队列
* 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型
* 栈1的push对应队列的deleteHead操作,栈2的pop操作对应队列的insertTail操作,当栈2为空时, 将栈1的元素依次出栈,进到栈2中,如果栈1也为空,则提示队列为空
*/
public class _09 {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
/**
* 队列的insertTail操作
* @param node 插入队尾的元素
*/
public void push(int node) {
stack1.push(node);
}
/**
* 队列的deleteHead操作
* @return 删除队列头部
*/
public int pop() {
if (stack2.empty()) {
if (stack1.empty()) {
throw new RuntimeException("队列为空");
} else {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
}
return stack2.pop();
}
}
10 斐波那契数列
/**
* 10 斐波那契数列
* 大家都知道斐波那契数列,后一项等于前两项和,现在要求输入一个整数n,请你输出斐波那契数列的 第n项(从0开始,第0项为0,n<=39)。
* 使用两个数将结果前两项缓存即可
*/
public class _10 {
public static int Fibonacci(int n) {
int result = 0;
int temp1 = 0;
int temp2 = 1;
if (n == 1) {
return temp2;
}
for (int i = 1; i < n; i++) {
result = temp1 + temp2;
temp1 = temp2;
temp2 = result;
}
return result;
}
public static void main(String[] args) {
System.out.println("Fibonacci(3) = " + Fibonacci(3));
}
}
剑指offer题解02-10的更多相关文章
- 剑指offer题解(Java版)
剑指offer题解(Java版) 从尾到头打印链表 题目描述 输入一个链表,按从尾到头的顺序返回一个ArrayList. 方法1:用一个栈保存从头到尾访问链表的每个结点的值,然后按出栈顺序将各个值存入 ...
- 剑指offer(leetcode 10.) 正则表达式匹配
这题一年前就做过,当时刚开始刷leetcode,提交了几十次过不去,就放那没管了.今天剑指offer又遇到这题,终于做出来了,用的dp. class Solution { public: bool i ...
- 剑指offer题解
数组中重复的数字 题目描述:在一个长度为n的数组里面的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字.例 ...
- 剑指Offer题解(Python版)
https://blog.csdn.net/tinkle181129/article/details/79326023# 二叉树的镜像 链表中环的入口结点 删除链表中重复的结点 从尾 ...
- 剑指offer第二版-10.斐波那契数列
面试题10:斐波那契数列 题目要求: 求斐波那契数列的第n项的值.f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2) n>1 思路:使用循环从下往上计算数列. 考点:考察对递归 ...
- 剑指offer——面试题10:斐波那契数列
个人答案: #include"iostream" #include"stdio.h" #include"string.h" using na ...
- 【剑指Offer】02、替换空格
题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 题解:StringBuffer ...
- 剑指Offer题解索引
数组 数组中重复的数字 二维数组中的查找 构建乘积数组 字符串 替换空格 字符流中第一个不重复的字符 表示数值的字符串 递归和循环 斐波那契数列 跳台阶 变态跳台阶 矩形覆盖 链表 从尾到头打印链表 ...
- 剑指offer【02】- 替换空格(Java)
题目:替换空格 考点:字符串 题目描述: 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. ...
随机推荐
- 【转】 VC++6.0 在Win7 64位下调试,Shift+F5无法退出
Win7 64位VC++6.0调试代码无法关闭窗口解决方法 VC++6.0 在64位Windows7下调试的时候,再结束调试,程序无法退出,只能关闭VC++6.0 IDE环境. 问题描述:当我击F5开 ...
- ASP.NET Web API中的路由
ASP.NET Web API的默认路由在App_Start目录中的WebApiConfig.cs文件中定义的. public static class WebApiConfig { public s ...
- hdu1814(2-SAT)
2-SAT 求出可能的解,但是这个解要是字典序最小的,所以只能采用2-SAT基本思想来解. 从小到大开始,对一个可能的点染色,染为1,然后dfs其所有能到达的点,如果其中出现一个已经标号为-1的话,那 ...
- 【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树
[BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度 ...
- [LeetCode] Reverse Lists
Well, since the head pointer may also be modified, we create a new_head that points to it to facilit ...
- 《挑战程序设计竞赛》2.3 动态规划-优化递推 POJ1742 3046 3181
POJ1742 http://poj.org/problem?id=1742 题意 有n种面额的硬币,面额个数分别为Ai.Ci,求最多能搭配出几种不超过m的金额? 思路 据说这是传说中的男人8题呢,对 ...
- 在Sql Server中使用证书加密数据
IF NOT EXISTS () CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'QWE23987zxJKL569&agf1$94467GRkjg5k3 ...
- android 反汇编一些资料
Android软件安全与逆向分析 http://book.2cto.com/201212/12432.html Smali--Dalvik虚拟机指令语言 http://blog.csdn.net/ ...
- Django限制请求method
1.常用的请求method 1.1 GET请求: GET请求一般用来向服务器索取数据,但不会向服务器提交数据,不会对服务器的状态进行更改.比如向服务器获取某篇文章的详情. 1.2 POST请求: PO ...
- Python高级教程-sorted
Python中的排序算法 排序是程序中经常用到的算法.通常规定,对于两个元素x和y,如果认为x<y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法 ...