剑指offer刷刷题

1、编程实现设计模式:Singleton(单例模式)

public class Singleton
{
 private Singleton(){}
 private static Singleton s = new Singleton();
 public static Singleton getSingleton()
 {
	 return s;
 }
}

2、在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 

public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) 
    {
    	if (length == 0 || length == 1)
    		return false;
    	for (int i = 0; i < length; i++)
    	{
    		if (numbers[i] != i)
    		{
    			if (numbers[i] == numbers[numbers[i]])
    			{
    				duplication[0] = numbers[i];
    				return true;
    			}
    			int temp = numbers[i];
    			numbers[i] = numbers[temp];
    			numbers[temp] = temp;
    			
    		}
    		
    	}
    	return false;
    }
}

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

思路:从右上角开始!

public class Solution 
{
	
    public boolean Find(int target, int [][] array)
    {
       if (array.length == 0) return false;
       int rows = array.length;
       int columns = array[0].length;
       int row = 0;
       int column = columns - 1;
       while (row < rows && column >=0)
       {
    	   if (target == array[row][column])
    		   return true;
    	   else if (target > array[row][column])
    		   row++;
    	   else
    		   column--;
       }
       return false;
    }
}

4、二叉树的下一结点:

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

思路: 

(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 Solution 
{
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if (pNode == null) return null;
        if (pNode.right != null)
        {
        	TreeLinkNode t1 = pNode.right;
        	while (t1.left != null)
        	{
        		t1 = t1.left;
        	}
        	return t1;
        }
        else if (pNode.next != null)
        {
        	TreeLinkNode curr = pNode;
        	TreeLinkNode parent = pNode.next;
        	while (parent != null && curr == parent.right)
        	{
        		curr = parent;
        		parent = parent.next;
        	}
        	return parent;
        }
        else 
        	return null;
    }
}
面试题11: 旋转数组的最小数字

思路: 二分查找,比较中间值mid与left的值,若mid > left 说明最小值在后半部分;否则,在前半部分。


import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) 
    {
     if (array.length == 1) return array[0]; 
     int l = 0;
     int r = array.length - 1;
     while (array[l] >= array[r])
     {
    	 if (r - l == 1) return array[r];
    	 int mid = l + (r - l) / 2;
    	 if (array[mid] >= array[l]) l = mid;
    	 else r = mid;
     }
     return array[l];
    }
}

面试题12:矩阵中的路径

思路:回溯法,递归。

public class Solution {
   public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
	 {
	    boolean[] visited = new boolean[cols * rows];
	    for (int i = 0; i < rows * cols; i++)
	    	visited[i] = false;
	    int Pathlenth = 0;
	    for (int row = 0; row < rows; row++)
	    	for (int col = 0; col < cols; col++)
	    	{
	    		if (hasPathCore(matrix, rows, cols, str, row, col, Pathlenth, visited))
	    			return true;
	    	}
	    return false;
	 }
private boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, int row, int col, int Pathlenth, boolean[] visited)
{
	if (Pathlenth >= str.length) return true;
	boolean hasPath = false;
	if (row >=0 && row < rows && col >=0 && col < cols && str[Pathlenth] == matrix[row * cols + col] && visited[row * cols + col] == false)
	{
		visited[row * cols + col] = true;
		Pathlenth++;
		hasPath = hasPathCore(matrix, rows, cols, str, row+1, col, Pathlenth, visited) || 
				hasPathCore(matrix, rows, cols, str, row-1, col, Pathlenth, visited) ||
				hasPathCore(matrix, rows, cols, str, row, col+1, Pathlenth, visited) ||
				hasPathCore(matrix, rows, cols, str, row, col-1, Pathlenth, visited);
		if (!hasPath)
		{
			visited[row * cols + col] = false;
			Pathlenth--;
		}
	}
   return hasPath;

}


}


面试题13:机器人的运动范围

思路: 回溯法,机器人从(0,0)点开始,某点能到达的方格数为1+ 该点上下左右能到达的方格数

public class Solution {
 public int movingCount(int threshold, int rows, int cols)
    {
    	boolean[] visited = new boolean[rows * cols];
    	for (int i = 0; i < rows * cols; i++)
    		visited[i] = false;
    	int count = movingCountCore(threshold, rows, cols, 0, 0, visited);
    	return count;
    			
        
    }
    private int movingCountCore(int threshold, int rows, int cols,int row, int col, boolean[] visited)
    {
    	int count = 0;
    	if (check(threshold, rows, cols, row, col, visited))
    	{
    		visited[row * cols + col] = true;
    		count = 1 + movingCountCore(threshold, rows, cols, row+1, col, visited) +  movingCountCore(threshold, rows, cols, row, col+1, visited)
    				  + movingCountCore(threshold, rows, cols, row-1, col, visited) +  movingCountCore(threshold, rows, cols, row, col-1, visited);
    	}
    	return count;
    }
    private boolean check (int threshold, int rows, int cols,int row, int col, boolean[] visited)
    {
    	if (row >= 0 && row < rows && col >= 0 && col < cols && digitsum(row,col,threshold) && visited[row * cols + col] == false)
    		return true;
    	else
    		 return false;
    }
    private boolean digitsum(int row, int col, int threshold)
    {
    	int sum1 = 0,sum2 = 0;
    	while (row > 0)
    	{
    		sum1 = sum1 + row % 10;
    		row = row / 10;
    	}
    	while (col > 0)
    	{
    		sum2 = sum2 + col % 10;
    		col = col / 10;
    	}
    	if (sum1 + sum2 <= threshold) return true;
    	else return false;
    		
    }
}

面试题15:二进制中1的个数

思路: 一个数字与其减1得到的数字按位与,会把该整数最右边的1变成0;

public class Solution
{
    public int NumberOf1(int n) 
    {
    	int sum = 0;
        while(n != 0)
        {
        	sum++;
            n = (n-1) & n;
        }
        return sum;
    }
    public static void main(String[]  args)
    {
    	Solution so = new Solution();
    	System.out.println(so.NumberOf1(5));
    }
}

面试题18:删除链表中重复的结点

思路:

(1)套用删除重复节点的思路,给定头结点与要删除的结点,将后一个结点的值赋给当前结点,删除后一节点。

第一步:(2)从头遍历链表,如当前结点与后一结点值相同,使用(1)删除后一节点,并记录值

第二步:(3)若当前结点值与记录值相同,删除当前结点(注意当前结点为头结点时的情况),更新当前结点。

第三步:(4)若不同于以上两种情况,更新当前结点。

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}.
*/
public class Solution
{
public ListNode deleteDuplication(ListNode pHead)
    {
		ListNode temp = pHead;
		ListNode pre = null;
		if (pHead == null || pHead.next == null) return pHead;
		int val = 0;
		boolean del = false;
		while (temp != null)
		{
			
			if (temp.next != null && temp.val == temp.next.val) 
			{
				val = temp.val;
				del = true;
				deletenode(pHead, temp.next);
			}
			else if (del && temp.val == val)
			{
				if (temp == pHead){ pHead = pHead.next; temp = pHead;}
				else
				{
					deletenode(pHead, temp); temp = pre;
				}
			}
			else
			{
				pre = temp;
				temp = temp.next;
			}
		}
		return pHead;
    }
	private void deletenode(ListNode listHead, ListNode toDelete)
	{
		if (listHead == null || toDelete == null) return;
		if (toDelete.next != null)
		{
			toDelete.val = toDelete.next.val;
			toDelete.next = toDelete.next.next;
			return;
		}
		else
		{
			ListNode pNode = listHead;
			while (pNode.next != toDelete)
			{
				pNode = pNode.next;
				
			}
			pNode.next = null;
			return;	
		}
	}
}

面试题19:正则表达式匹配

思路:(1)若模式中下一个字符不是“*”,那么只用比较,然后将pattern,str指针分别后移即可。

(2)若模式下一个字符为“*”,则str当下字符可跟pattern当下字符比较;跟‘*’后字符比较;str下一个字符可跟pattern当下字符比较。

public class Solution {
    public boolean match(char[] str, char[] pattern)
	 {
	  if (str.length == 0 && pattern.length == 0) return true;
	  if (pattern.length == 0 && str.length != 0) return false;
	  return isMatch(0, 0, str, pattern);
	 }
	 private boolean isMatch(int i, int j, char[] str, char[] pattern)
	 {
		 if (str.length <= i && pattern.length <= j) return true;
		 if (str.length > i && pattern.length <= j) return false;
		 if (j + 1 < pattern.length &&  pattern[j+1] == '*')
		 {
			 if ((str.length > i && str[i] == pattern[j]) || (pattern[j] == '.' && str.length > i))
			 {
				 return (isMatch(i + 1, j, str, pattern) || isMatch(i + 1, j + 2, str, pattern) || isMatch(i, j + 2, str, pattern));
			 }
			 else
				 return isMatch(i, j + 2, str, pattern);
		 }
		 if ((str.length > i && pattern.length > j && str[i] == pattern[j]) || (pattern.length > j && str.length > i && pattern[j] == '.' ))
			 return isMatch(i + 1, j + 1, str, pattern);
		 return false;
	 }
}







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值