面試題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;
}
}