面试题3:数组中重复的数字
import java.util.Arrays;
/**
* P39 面试题3:数组中重复的数字
* 在一个长度为n的数组里所有数字都在0~n-1的范围内 数组中某些数字是重复的 但不知道有几个数字重复了
* 也不知道每个数字重复了几次 请找出数组中任意一个重复的数字
* 例如 如果输入长度为7的数组{2,3,1,0,2,5,3}
* 那么对应的输出是重复的数字2或者3
* @author tzy
*
*/
public class T3
{
public static void main(String[] args)
{
int[] duplication=new int[1]; //保存答案的数组 结果保存在[0]
int[] inputarr={11,22,1,0,2,5,5};
}
/*
* 解法1:排序数组后找到重复值
* 排序算法的时间复杂度为O(nlogn)
*/
public static boolean solution1(int[] numbers,int length,int[] duplication)
{
if(numbers==null||length<=0)
{
return false;
}
Arrays.parallelSort(numbers);
for(int i=0;i<numbers.length-1;i++)
{
if(numbers[i]==numbers[i+1])
{
duplication[0]=numbers[i];
return true;
}
}
return false;
}
/*
* 解法2:使用哈希表
* 时间复杂度O(N) 空间复杂度O(N)
*/
public static boolean solution2(int[] numbers,int length,int[] duplication)
{
int temp[]=new int[length+1];
if(numbers==null||length<=0)
{
return false;
}
for(int i=0;i<length;i++)
{
temp[numbers[i]]++;
}
for(int j=0;j<length;j++)
{
if(temp[j]>1)
{
duplication[0]=j;
return true;
}
}
return false;
}
/*
* 解法3 推荐解法
* 时间复杂度O(N) 空间复杂度O(1)
* 通过将下标为i的数字(称为m)调整到属于它的下标的位置
*/
public static boolean solution3(int[] numbers,int length,int[] duplication)
{
if(numbers==null||length<=0)
{
return false;
}
for(int i=0;i<length;i++)
{
while(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;
}
}
面试题4:二维数组中的查找
/*
* P44面试题4:二维数组中的查找
* 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序
* 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
*/
public class T4
{
/*
* 思路:对于二维数组中的每一个数字,他小于他右边的数字,小于他下方的数字
* 所以从右上角的数字(称为m)开始查找
* 若m>target 则剔除m所在的列 因为m是这一列最小的元素 这一列所有的元素将大于target
* 若m<target 则剔除m所在的行 因为m是这一行最小的元素 这一行所有的元素将小于target
*/
public boolean Find(int target, int [][] array)
{
if(array.length==0||array[0].length==0||array==null)
{
return false;
}
//记录行数与列数
int rows=array.length;
int cols=array[0].length;
//从右上角开始搜索
int rownow=0;
int colnow=cols-1;
while(rownow<=rows-1&&colnow>=0)//搜索到最左下角的数字是边界条件
{
if(array[rownow][colnow]==target)
{
return true;
}
else if(array[rownow][colnow]>target)
{
colnow--;
}
else
{
rownow++;
}
}
return false;
}
}
面试题5:替换空格
/*
* P51面试题5:替换空格
* 题目:请实现一个函数,把字符串中的每个空格替换成"%20"
* 例如输入"We are happy."
* 则输出"We%20are%20happy."
*/
public class T5
{
/*
* 解题思路:
* 先遍历一遍数组 找到一共有多少个空格 在尾部添加2*空格个数的任意字符
* 令P1指向原末尾,P2指向延长后的末尾,两指针均从后往前遍历(P1开始)
* 每当P1遍历到一个字符时 将它复制到P2 两指针同时前移一位
* 当P1遍历到空格时 P1向前移一位 P2向前移动三位并填充02%
* 当P1与P2重合时 则结束
* 从后向前遍历是为了在改变P2所指向的内容时 不会影响到P1遍历原来的字符串内容
*/
public String replaceSpace(StringBuffer str)
{
int P1=str.length()-1;
for(int i=0;i<=P1;i++)
{
if(str.charAt(i)==' ')
{
str.append(" ");
}
}
int P2=str.length()-1;
while(P1!=P2)
{
if(str.charAt(P1)!=' ')
{
str.setCharAt(P2, str.charAt(P1));
P1--;
P2--;
}
else
{
P1--;
str.setCharAt(P2--, '0');
str.setCharAt(P2--, '2');
str.setCharAt(P2--, '%');
}
}
return str.toString();
}
}
面试题6:从尾到头打印链表
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
/*
* P58面试题6:从尾到头打印链表
* 题目:输入一个链表的头结点,从尾到头反过来打印出每个节点的值
*/
public class T6
{
/*
* 解法一:使用栈
* 由于栈的“后进先出特性” 对链表进行一次遍历后依次弹出
* 得到的顺序即为逆序
*/
public ArrayList<Integer> printListFromTailToHead1(ListNode listNode)
{
Stack<Integer> stack=new Stack<Integer>();
while(listNode!=null)
{
stack.add(listNode.val);
listNode=listNode.next;
}
ArrayList<Integer> res=new ArrayList<Integer>();
while(!stack.isEmpty())
{
res.add(stack.pop());
}
return res;
}
/*
* 解法二:使用递归
* 递归的本质就是一个栈结构 所以可以自然地想到用递归来实现
* 具体实现为:每访问到一个节点的时候,先递归输出它后面的节点,再输出该节点自身
* 但该方法若是输入的链表长度非常长时
* 会导致函数调用的层级过深
* 从而导致函数调用栈溢出(java.lang.StackOverflowError)
*/
public ArrayList<Integer> printListFromTailToHead2(ListNode listNode)
{
ArrayList<Integer> res=new ArrayList<Integer>();
if(listNode!=null)
{
res.addAll(printListFromTailToHead2(listNode.next));
res.add(listNode.val);
}
return res;
}
/*
* 解法三:使用头插法
* 由于头插法的性质是每次插入在头部
* 所以使用头插法重新构建链表后即为逆序
* 注意点:
* 头结点是在头插法中使用的一个额外节点,这个节点不存储值
* 第一个节点就是链表的第一个真正存储值的节点
*/
public ArrayList<Integer> printListFromTailToHead3(ListNode listNode)
{
ListNode head=new ListNode(-1);//头结点
while(listNode!=null)
{
ListNode temp=new ListNode(listNode.val);
temp.next=head.next;
head.next=temp;
listNode=listNode.next;
}
ArrayList<Integer> res=new ArrayList<Integer>();
head=head.next;
while(head!=null)
{
res.add(head.val);
head=head.next;
}
return res;
}
/*
* 解法四:使用Collection.reverse()
*/
public ArrayList<Integer> printListFromTailToHead4(ListNode listNode)
{
ArrayList<Integer> res=new ArrayList<Integer>();
while(listNode!=null)
{
res.add(listNode.val);
listNode=listNode.next;
}
Collections.reverse(res);
return res;
}
}