【劍指 Offer】3~10
技術標籤:Java Program連結串列字串java資料結構
文章目錄
3、陣列中重複的數字
找出陣列中重複的數字
在一個長度為 n 的陣列 nums 裡的所有數字都在 0~n-1 的範圍內。陣列中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。
示例1:
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3
限制:
2 <= n <= 100000
解析:
從頭掃描陣列,一個蘿蔔一個坑,遇到下標為i的數字如果不是i的話,(假設數字為m),那麼我們就拿與下標m的數字交換,直到交換到下標i的數字也是i為止。交換期間,如果下標為i的數字等於下標為m的數字,那就返回該數字,即找到重複數字。
class Solution {
public int findRepeatNumber(int[] nums) {
int temp;
for(int i=0;i<nums.length;i++){
while(nums[i]!=i){
if(nums[i]==nums[nums[i]]){
return nums[i];
}
temp = nums[i];
nums[ i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
}
4、二維陣列中的查詢
在一個 n * m 的二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個高效的函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
示例 1:
現有矩陣 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
給定 target = 5,返回 true。
給定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
解析:
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int row = 0;
int col = matrix[0].length - 1;
while (row <= matrix.length - 1 && col >= 0) {
if (target > matrix[row][col]) {
row++;
} else if (target < matrix[row][col]) {
col--;
} else {
return true;
}
}
return false;
}
}
5、替換空格
請實現一個函式,把字串 s 中的每個空格替換成"%20"。
示例 1:
輸入:s = "We are happy."
輸出:"We%20are%20happy."
限制:
0 <= s 的長度 <= 10000
解析:
方法一:遍歷 + 快取
class Solution {
public String replaceSpace(String s) {
StringBuffer sb = new StringBuffer();
for(int i=0; i<s.length(); i++){
if(s.charAt(i) == ' '){
sb.append("%20");
}else {
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
方法二:呼叫api介面
class Solution {
public String replaceSpace(String s) {
return s.replaceAll(" ","%20");
}
}
方法三:遍歷 + 字元陣列
由於空格要替換為%20,那麼,可以宣告一個字元陣列,大小是字串的3倍。依次遍歷字串,逐漸將字元填入字元陣列之中,當遇到空格時,變為新增%、2、0三個字元。最後,生成新的字串,擷取字元陣列中有效的部分即可,即字元陣列從0開始,長度為有效儲存進字元陣列的長度。
class Solution {
public String replaceSpace(String s) {
char[] ch = new char[s.length() * 3];
int index = 0;
for(int i=0; i<s.length(); i++){
char c = s.charAt(i);
if(c == ' '){
ch[index++] = '%';
ch[index++] = '2';
ch[index++] = '0';
}else {
ch[index++] = c;
}
}
return new String(ch, 0, index);
}
}
6、從尾到頭列印連結串列
輸入一個連結串列的頭節點,從尾到頭反過來返回每個節點的值(用陣列返回)。
示例 1:
輸入:head = [1,3,2]
輸出:[2,3,1]
限制:
0 <= 連結串列長度 <= 10000
解析:
方法一:遞迴
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
ArrayList<Integer> temp = new ArrayList<Integer>();
public int[] reversePrint(ListNode head) {
reverse(head);
int [] arr = new int [temp.size()];
for(int i=0;i<arr.length;i++){
arr[i]=temp.get(i);
}
return arr;
}
public void reverse(ListNode head){
if(head==null){
return;
}
reverse(head.next);
temp.add(head.val);
}
}
方法二:棧
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode temp = head;
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] res = new int[size];
for (int i = 0; i < size; i++) {
res[i] = stack.pop().val;
}
return res;
}
方法三:逆序儲存
public int[] reversePrint(ListNode head) {
if (head == null) return new int[]{};
// 1. 計算連結串列的長度
int length = 0;
ListNode curr = head;
while (curr != null) {
length++;
curr = curr.next;
}
// 2. 初始化存放結果的陣列
int[] res = new int[length];
// 3. 按照反方向將連結串列節點值存放在陣列中
int i = length - 1;
curr = head;
while (curr != null) {
res[i] = curr.val;
i--;
curr = curr.next;
}
return res;
}