public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
需要使用static来保证是类层面的
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
(3)双重锁
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
public class Singleton{
private static class SingletonHandler{
public static Singleton newInstance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonHandler.newInstance;
}
}
private static boolean isIn(int[][] a,int num){
int m = a.length;
int n = a[0].length;
int i = 0;
while(i < m & n > 0){
if(a[i][n-1] == num){
return true;
}else if(a[i][n-1] > num){
n--;
}else{
i++;
}
}
return false;
}
面试题4:替换空格
时间复杂度:O(n),空间复杂度
public static void main(String[] args) {
char[] arr = {'w','e',' ','a','r','e',' ','h','a','p','p','y'};
String str = new String(arr);
System.out.println(""+replace2(str));
System.out.println(""+replace3(arr));
}
public static String replace3(char[] arr){
if(arr == null || arr.length == 0){
return "";
}
int len = arr.length;
int count = 0;
for(int i = 0; i < len; i++){
if(arr[i] == ' ')
count++;
}
int nlen = len + count*2;
char[] res = new char[nlen];
int p1 = len - 1;
int p2 = nlen - 1;
while(p1 >= 0 && p2 >= 0){
if(arr[p1] == ' '){
res[p2--] = '0';
res[p2--] = '2';
res[p2--] = '%';
}else{
res[p2--] = arr[p1];
}
p1--;
}
return new String(res);
}
public static String replace2(String str){
if(str == null || str.length() == 0){
return "";
}
int len = str.length();
StringBuilder res = new StringBuilder();
for(int i = 0; i < len; i++){
if(str.charAt(i) == ' '){
res.append("%20");
}else{
res.append(str.charAt(i));
}
}
return res.toString();
}/*当使用split的时候要考虑可能会出现几个空格相连的情况,还有全是空格的情况,这时候用split其实就不可取了*/
public static void printList(ListNode head){
if(head == null)
return;
Stack<ListNode> stack = new Stack<ListNode>();
while(head != null){
stack.push(head);
head = head.next;
}
while(!stack.isEmpty()){
System.out.print(stack.pop().val+" ");
}
}/*当链表很长的时候用递归可能会栈溢出,所以还是使用栈的方法鲁棒性更好*/
public static void printList2(ListNode head){
if(head == null)
return;
if(head.next != null)
printList2(head.next);
System.out.print(head.val+" ");
}
public static TreeNode reBuild(int[] preorder, int[] inorder){
if(preorder == null || inorder == null || inorder.length <= 0 || inorder.length != preorder.length){
return null;
}
int len = inorder.length;
return constructTree(preorder,inorder,0,len-1,0,len-1);
}
public static TreeNode constructTree(int[] preorder, int[] inorder, int pstart, int pend, int istart, int iend){
if(pstart > pend || istart > iend)
return null;
int rootVal = preorder[pstart];
TreeNode root = new TreeNode(rootVal);
int index = -1;
for(int i = istart; i <= iend; i++){
if(inorder[i] == rootVal){
index = i;
break;
}
}
int cur = index - istart;
TreeNode left = constructTree(preorder, inorder, pstart+1, pstart + cur, istart, index - 1);
TreeNode right = constructTree(preorder, inorder, pstart + cur + 1, pend, index + 1, iend);
root.left = left;
root.right = right;
return root;
}
public class stackToQueue7 {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public int pop(){
int res = -1;
if(!stack2.isEmpty()){
res = stack2.pop();
}else{
while(!stack1.isEmpty()){
int tmp = stack1.pop();
stack2.push(tmp);
}
if(!stack2.isEmpty()){
res = stack2.pop();
}
}
return res;
}
public void push(int num){
stack1.push(num);
}
}
public class queueToStack7 {
Queue<Integer> queue1 = new LinkedList<Integer>();
Queue<Integer> queue2 = new LinkedList<Integer>();
public int pop() throws Exception{
if(queue1.isEmpty() && queue2.isEmpty()){
throw new Exception("stack is empty");
}
if(queue1.isEmpty()){
while(queue2.size() > 1){
queue1.add(queue2.poll());
}
return queue2.poll();
}
if(queue2.isEmpty()){
while(queue1.size() > 1){
queue2.add(queue1.poll());
}
return queue1.poll();
}
return (Integer) null;
}
public void push(int num){
if(queue1.isEmpty() && queue2.isEmpty()){
queue1.add(num);
return;
}
if(!queue1.isEmpty()){
queue1.add(num);
return;
}
if(!queue2.isEmpty()){
queue2.add(num);
return;
}
}
}
public static int minInSpiral(int[] arr) throws Exception{
if(arr == null || arr.length == 0){
throw new Exception("Error");
}
int p1 = 0;
int p2 = arr.length - 1;
int mid = p1;
while(arr[p1] >= arr[p2]){
if(p2 - p1 == 1){
mid = p2;
break;
}
mid = (p1 + p2) / 2;
if(arr[p1] == arr[p2] && arr[p1] == arr[mid]){
return getMinorder(arr,p1,p2);
}
if(arr[p1] <= arr[mid]){
p1 = mid;
}else if(arr[p2] >= arr[mid]){
p2 = mid;
}
}
return arr[mid];
}
public static int getMinorder(int[] arr,int start, int end){
int tmp = arr[start];
for(int i = start+1; i <= end; i++){
if(arr[i] < tmp)
tmp = arr[i];
}
return tmp;
}
面试题9:斐波那契数列
private static long[] frr = new long[10000];
public static long fabon(int n){
if(n == 0)
return 0;
if(n == 1)
return 1;
if(frr[n] != 0)
return frr[n];
frr[n] = fabon(n-1) + fabon(n-2);
return frr[n];
}/*递归的方法,但是效率和空间利用率都很低,且容易栈溢出*/
public static int Fibonacci(int n) {
if(n == 0)
return 0;
if(n == 1)
return 1;
int a1 = 1;
int a2 = 1;
for(int i=3;i<=n;i++){
int tmp = a2;
a2 = a1 + a2;
a1 = tmp;
}
return a2;
}/*时间复杂度是O(n),但是很使用*/
public int NumberOf1(int n) {
int res = 0;
while( n != 0){
res++;
n = n & (n -1);
}
return res;
}
相似的问题还有:判断一个数是否是2的整数次方(就用n&(n-1));
public static double getPow(double base, int exp) throws Exception{
if(equal(base,0.0) && exp < 0)
throw new Exception("0 error");
if(exp == 0)
return 1.0;
int tmp = 0;
if(exp < 0){
tmp = exp;
exp = - exp;
}
double res = getPowtmp(base,exp);
if(tmp != 0){
res = 1.0 / res;
}
return res;
}
public static double getPowtmp(double base, int exp){
if(exp == 0)
return 1.0;
if(exp == 1)
return base;
double result = getPowtmp(base,exp >> 1);
result *= result;
if((exp & 0x1) == 1){
result *= base;
}
return result;
}
public static boolean equal(double d1, double d2){
if(d1 - d2 > -0.0000001 && d1 - d2 < 0.0000001){
return true;
}
return false;
}
public static void printN(int n){
if(n <= 0)
return;
char[] number = new char[n+1];
for(int i = 0; i < n+1; i++){
number[i] = '0';
}
while(!increment(number)){
sprint(number);
}
}
public static void sprint(char[] arr){
int len = arr.length;
boolean isStart = false;
for(int i = 0; i < len; i++){
if(!isStart && arr[i] != '0')
isStart = true;
if(isStart){
System.out.print(arr[i]);
}
}
}
public static boolean increment(char[] arr){
boolean res = false;
int cre = 1;
int len = arr.length;
for(int i = len - 1; i >= 0; i--){
int sum = arr[i] - '0' + cre;
if(sum >= 10){
if(i == 0)
res = true;
else{
sum -= 10;
cre = 1;
arr[i] = (char) ('0' + sum);
}
}else{
arr[i] = (char)('0' + sum);
break;
}
}
return res;
}
public static void printN2(int n){
if(n <= 0)
return;
char[] number = new char[n+1];
for(int i = 0; i < n+1; i++){
number[i] = '0';
}
for(int i = 0; i < 10; i++){
number[0] = (char)(i + '0');
printRe(number,n,0);
}
}
public static void printRe(char[] arr,int len, int index){
if(index == len - 1){
sprint(arr);
return;
}
for(int i = 0; i < 10; i++){
arr[index+1] = (char)(i + '0');
printRe(arr,len,index+1);
}
}
public static void deleteOne(ListNode head,ListNode del){
if(head == null || del == null)
return;
if(del.next != null){
del.val = del.next.val;
del.next = del.next.next;
}else if(del == head){
head = null;
}else{
ListNode tmp = head;
while(tmp.next != del)
tmp = tmp.next;
tmp.next = null;
}
}
public static void changeOrder(int[] arr){
if(arr == null)
return;
int len = arr.length;
int start = 0;
int end = len - 1;
while(start < end){
while(start < end && !isEven(arr[start])){
start++;
}
while(start < end && isEven(arr[end]))
end--;
if(start < end){
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
}
}
public static boolean isEven(int n){
if((n & 1) == 0){
return true;
}
return false;
}
public static ListNode getKth(ListNode head,int k){
if(head == null || k <= 0)
return null;
ListNode pre = head;
for(int i = 0; i < k; i++){
pre = pre.next;
if(pre == null)
return pre;
}
ListNode cur = head;
while(pre != null){
pre = pre.next;
cur = cur.next;
}
return cur;
}
public static ListNode reverse(ListNode head){
ListNode pre = null;
ListNode cur = head;
ListNode tmp = null;
while(cur != null){
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
public static ListNode mergeTwo(ListNode list1,ListNode list2){
if(list1 == null)
return list2;
if(list2 == null)
return list1;
ListNode nHead = null;
if(list1.val >= list2.val){
nHead = list1;
list1 = list1.next;
}else{
nHead = list2;
list2 = list2.next;
}
ListNode p = nHead;
while(list1 != null && list2 != null){
if(list1.val >= list2.val){
p.next = list1;
list1 = list1.next;
}else{
p.next = list2;
list2 = list2.next;
}
p = p.next;
}
p.next = list1 == null ? list2 : list1;
return nHead;
}
public static boolean isSubtr(TreeNode pRoot,TreeNode sRoot){
if(pRoot == null || sRoot == null)
return false;
return isSubImpl(pRoot,sRoot);
}
public static boolean isSubImpl(TreeNode pRoot,TreeNode sRoot){
if(sRoot == null)
return true;
if(pRoot == null)
return false;
boolean res = false;
if(pRoot.val == sRoot.val){
res = isSubImpl(pRoot.left,sRoot.left) && isSubImpl(pRoot.right,sRoot.right);
}
if(!res){
res = isSubImpl(pRoot.left,sRoot) || isSubImpl(pRoot.right,sRoot);
}
return res;
}
public static void mirror(TreeNode root){
if(root == null || (root.left == null && root.right == null))
return ;
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
if(root.left != null){
mirror(root.left);
}
if(root.right != null)
mirror(root.right);
}
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
if(matrix == null || matrix.length ==0 || matrix[0].length == 0)
return null;
int rows = matrix.length;
int cols = matrix[0].length;
int start = 0;
ArrayList<Integer> res = new ArrayList<>();
while(cols > start * 2 && rows > start * 2){
printMatrixInCircle(res, matrix, rows, cols, start);
start++;
}
return res;
}
private void printMatrixInCircle(ArrayList<Integer> res, int[][] arr, int row, int col,int start){
int endX = col - 1 - start;
int endY = row - 1 - start;
//从左到右打印
for(int i = start; i <= endX; i++){
res.add(arr[start][i]);
}
//从上到下打印最右边一列
if(endY > start){
for(int i = start + 1; i <= endY; i++){
res.add(arr[i][endX]);
}
}
//从右到左打印最后一行
if(endX > start && endY > start){
for(int i = endX - 1; i >= start; i--){
res.add(arr[endY][i]);
}
}
//从下到上打印第一列
if(endX > start && endY > start + 1){
for(int i = endY - 1; i > start; i--){
res.add(arr[i][start]);
}
}
}
}
public static void printCircle(int[][] matrix) {
if (matrix == null)
return;
int rows = matrix.length;
int cols = matrix[0].length;
int left = 0;
int top = 0;
int right = cols - 1;
int bottom = rows - 1;
while (top <= bottom && left <= right) {
for (int i = left; i <= right; i++) {
System.out.print(matrix[top][i] + " ");
}
top++;
if (top > bottom)
break;
for (int j = top; j <= bottom; j++) {
System.out.print(matrix[j][right] + " ");
}
right--;
if (right < left)
break;
for (int i = right; i >= left; i--) {
System.out.print(matrix[bottom][i] + " ");
}
bottom--;
for (int j = bottom; j >= top; j--) {
System.out.print(matrix[j][left] + " ");
}
left++;
}
}
public static void printTreeNode(TreeNode root){
if(root == null)
return;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
System.out.print(cur.val + " ");
if(cur.left != null)
stack.push(root.left);
if(cur.right != null)
stack.push(root.right);
}
}
public static boolean isPost(int[] arr,int start, int end){
if(arr == null || arr.length == 0)
return false;
int root = arr[end];
int i = start;
for(; i < end; i++){
if(arr[i] > root)
break;
}
for(int j = i; j < end; j++){
if(arr[j] < root)
return false;
}
boolean left = true;
if(i > start)
left = isPost(arr,start,i-1);
boolean right = true;
if(i < end)
right = isPost(arr,i,end-1);
return left & right;
}
public static ArrayList<ArrayList<Integer>> getPath(TreeNode root,int sum){
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(root == null)
return res;
ArrayList<Integer> li = new ArrayList<Integer>();
getPathImpl(root,sum,res,li);
return res;
}
public static void getPathImpl(TreeNode root, int sum, ArrayList<ArrayList<Integer>> res, ArrayList<Integer> li){
if(root == null)
return;
li.add(root.val);
sum -= root.val;
if(root.left == null && root.right == null){
if(sum == 0){
res.add(new ArrayList<Integer>(li));
}
}else{
if(root.left != null)
getPathImpl(root.left,sum,res,li);
if(root.right != null)
getPathImpl(root.right,sum,res,li);
}
li.remove(li.size() - 1);
}
public class Solution {
public int InversePairs(int [] array) {
if(array == null || array.length == 0){
return 0;
}
return getInversePairs(array, 0, array.length - 1);
}
private int getInversePairs(int[] arr, int start,int end){
if(start == end)
return 0;
int mid = (start + end) >> 1;
int left = getInversePairs(arr, start, mid) % 1000000007;
int right = getInversePairs(arr, mid + 1, end) % 1000000007;
int lend = mid;
int rend = end;
int copyLen = end - start + 1;
int[] copy = new int[copyLen];
//逆序对
int count = 0;
int copyIndex = copyLen - 1;
while(lend >= start && rend >= mid + 1){
if(arr[lend] > arr[rend]){
count += rend - mid;
if(count >= 1000000007){
count %= 1000000007;
}
copy[copyIndex] = arr[lend];
lend--;
}else{
copy[copyIndex] = arr[rend];
rend--;
}
copyIndex--;
}
//处理两个数组剩下的部分
while(lend >= start){
copy[copyIndex--] = arr[lend--];
}
while(rend >= mid + 1){
copy[copyIndex--] = arr[rend--];
}
//复制回原来的数组
for(int i = 0; i < copyLen; i++){
arr[i + start] = copy[i];
}
return (count + left + right) % 1000000007;
}
}
public static String reverseStr(String s){
if(s == null || s.length() == 0){
return "";
}
int len = s.length();
char[] arr = s.toCharArray();
reverse(arr,0,len-1);
int count = 0;
for(int i = 0; i < len; i++){
if(arr[i] != ' ')
count++;
else{
if(count > 1){
reverse(arr,i - count,i-1);
}
count = 0;
}
}
return String.valueOf(arr);
}
public static void reverse(char[] arr,int start,int end){
while(start < end){
char tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
start++;
end--;
}
}
public class Solution {
public String ReverseSentence(String str) {
if(str == null || str.length() < 2)
return str;
String res = "";
String[] arr = str.split(" ");
int len = arr.length;
if(len > 0){
for(int i = len - 1; i > 0; i--){
res += arr[i] + " ";
}
res += arr[0];
}else{
res = str;
}
return res;
}
}
1.矩阵中的路径(网上的)
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
解答:
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
//创建一个布尔数组
boolean visited[]= new boolean[matrix.length];
for(int i = 0;i<rows;i++){
for(int j=0;j<cols;j++){
if(hasPathCore(matrix,i,j,0,rows,cols,str,visited)){
return true;
}
}
}
return false;
}
public boolean hasPathCore(char[] matrix,int i,int j,int k,int rows,int cols,char[] str,boolean[] visited){
// 对于给定行数和列数得到其在矩阵中的下标
int index = i*cols+j;
//判断合法性
if(i<0||i>=rows||j<0||j>=cols||matrix[index]!=str[k]||visited[index]){
return false;
}
visited[index] = true;
// 如果递归到最后一个位置的字符,则表明前面位置的字符都在矩阵中找到了对应的位置
if (k == str.length - 1)
return true;
if(hasPathCore(matrix,i-1,j,k+1,rows,cols,str,visited)
||hasPathCore(matrix,i,j-1,k+1,rows,cols,str,visited)
||hasPathCore(matrix,i+1,j,k+1,rows,cols,str,visited)
||hasPathCore(matrix,i,j+1,k+1,rows,cols,str,visited)){
return true;
}else{
//如果相邻格子的字符都没有匹配到下一个字符,则需要回到前一个格子,从而需要把把位置的状态重新设定为未访问
k--;
visited[index] = false;
}
return false;
}
}
2.机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解答:
import java.util.Stack;
public class Solution {
public int movingCount(int threshold, int rows, int cols) {
// 创建一个数组记录一个格子是否被访问
boolean[][] visited = new boolean[rows][cols];
return movingCountCore(threshold, rows, cols, 0, 0, visited);
}
private int movingCountCore(int threshold, int rows, int cols, int i,int j, boolean[][] visited) {
int count = 0;
// 异常处理
if (i < 0 || i >= rows || j < 0 || j >= cols
|| numberIndexCount(i) + numberIndexCount(j) > threshold
|| visited[i][j])
return 0;
visited[i][j] = true;
count = 1 + movingCountCore(threshold, rows, cols, i - 1, j, visited)
+ movingCountCore(threshold, rows, cols, i + 1, j, visited)
+ movingCountCore(threshold, rows, cols, i, j - 1, visited)
+ movingCountCore(threshold, rows, cols, i, j + 1, visited);
return count;
}
// 用于计算每个坐标的数位之和
private int numberIndexCount(int number) {
int sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
public static void main(String[] args) {
int sum = new Solution().movingCount(5, 10, 10);
System.out.println(sum);
}
}
import java.util.Stack;
public class Solution {
int movingCount(int threshold, int rows, int cols){
if(threshold<=0) return 0;
Stack<Integer> stack_x = new Stack<Integer>();
Stack<Integer> stack_y = new Stack<Integer>();
boolean flag[][] = new boolean[rows][cols];
stack_x.push(0);stack_y.push(0);
int count = 0;
int x = 0;int y = 0;flag[0][0] = true;
while(stack_x.size()!=0 && stack_y.size()!=0){
x = stack_x.peek();y = stack_y.peek();
//上
if((x-1)>=0 && !flag[x-1][y] && checkGo(threshold, x-1, y)){
stack_x.add(x-1);
stack_y.add(y);
flag[x-1][y] = true;
continue;
}
//下
if((x+1)<rows && !flag[x+1][y] && checkGo(threshold, x+1, y)){
stack_x.add(x+1);
stack_y.add(y);
flag[x+1][y]=true;
continue;
}
//左
if((y-1)>=0 && !flag[x][y-1] && checkGo(threshold, x, y-1)){
stack_x.add(x);
stack_y.add(y-1);
flag[x][y-1]=true;
continue;
}
//右
if((y+1)<cols && !flag[x][y+1] && checkGo(threshold, x, y+1)){
stack_x.add(x);
stack_y.add(y+1);
flag[x][y+1]=true;
continue;
}
stack_x.pop();stack_y.pop();
count++;
}
return count;
}
boolean checkGo(int k,int rows,int cols){
int n = 0;
while(rows>0){
n += rows%10;
rows /= 10;
}
while(cols>0){
n += cols%10;
cols /= 10;
}
if(n>k) return false;
return true;
}
}
66.序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树。
public class Solution {
public int index = -1;
String Serialize(TreeNode root) {
StringBuffer sb = new StringBuffer();
if(root == null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val + ",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
index++;
int len = str.length();
if(index >= len){
return null;
}
String[] strr = str.split(",");
TreeNode node = null;
if(!strr[index].equals("#")){
node = new TreeNode(Integer.valueOf(strr[index]));
node.left = Deserialize(str);
node.right = Deserialize(str);
}
return node;
}
}