劍指Offer刷題Day1

劍指Offer

Day 1

3. 數組中重複的數字

解題關鍵: 數組nums的長度爲n,且裏面的數字取值範圍是[0, n-1]。

思路一

通過開闢一個新的數組array,array的index代表nums數組中的值,array的值代表nums數組中元素出現的次數。

複雜度: 時間複雜度:O(n),空間複雜度:O(n)

public int findRepeatNumber(int[] nums) {
  int[] array = new int[nums.length];
  int ans = -1;
  for(int i = 0; i < nums.length; i++) {
    array[nums[i]] += 1;
    if (array[nums[i]] > 1) {
      ans = nums[i];
    }
  }
  return ans;
}

思路二

通過交換,讓每個數字出現在其應該出現的位置

複雜度: 時間複雜度:O(n),空間複雜度:O(1)

public int findRepeatNumber(int[] nums) {
  boolean flag = false;
  int ans = -1;
  for (int i = 0; i < nums.length; i++) {
    if (nums[i] == i) {
      continue;
    }
    while (nums[i] != i) {
      if (nums[i] == nums[nums[i]]) {
        ans = nums[i];
        flag = true;
        break;
      } else {
        int tmp = nums[i];
        nums[i] = nums[nums[i]];
        nums[tmp] = tmp;
      }
    }
    if (flag == true) {
      break;
    }
  }
  return ans;
}

4. 二維數組中的查找

二維數組的規律:每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。

思路一

利用規律進行查找元素:從右上角開始,假設要查找的數字是x。

  • 如果當前數字大於x,那麼就向左查找;
  • 如果當前數字小於x,那麼就向下查找;
  • 如果當前數字等於x,那麼就查找完畢,返回true;
  • 如果越界了,那麼查找完畢,返回false。

複雜度: 時間複雜度:O(n),空間複雜度:O(1)

public boolean findNumberIn2DArray(int[][] matrix, int target) {
  if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
    return false;
  }
  int width = matrix[0].length;
  int height = matrix.length;
  int row = 0;
  int col = width - 1;
  boolean ans = false;
  while (row < height && col >= 0) {
    if (matrix[row][col] == target) {
      ans = true;
      break;
    } else if (matrix[row][col] > target) {
      col--;
    } else if (matrix[row][col] < target) {
      row++;
    }
  }
  return ans;
}

5. 替換空格

請實現一個函數,把字符串 s 中的每個空格替換成"%20"。

思路一

使用 StringBuilder ,加額外的空間進行組裝

複雜度: 時間複雜度:O(n),空間複雜度:O(n)

public String replaceSpace(String s) {
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) == ' ') {
      sb.append("%20");
    } else {
      sb.append(s.charAt(i));
    }
  }
  return sb.toString();
}

思路二

使用char[]數組,該數組的長度設置爲當前長度的3倍,確保即使當前字符串全部是空格,也可以放得下。

複雜度: 時間複雜度:O(n),空間複雜度:O(3n)

public String replaceSpace(String s) {
  char[] chars = new char[s.length() * 3];
  char[] ss = s.toCharArray();
  int index = 0;
  for (char c : ss) {
    if (c == ' ') {
      chars[index++] = '%';
      chars[index++] = '2';
      chars[index++] = '0';
    } else {
      chars[index++] = c;
    }
  }
  return new String(chars, 0, index);
}

Tips: 將字符數組轉化成String的方式

String(byte[] bytes, int offset, int length);

Constructs a new String by decoding the specified subarray of bytes using the platform’s default charset.

6. 從尾到頭打印鏈表

思路一:

不考慮時間複雜度或者其他因素,可以直接通過將鏈表壓入棧,緊接着彈出,就可以打印鏈表。

Java中官方JDK不推薦使用Stack。但是就算法題來說,爲了說明算法還是使用了Stack

public int[] reversePrint(ListNode head) {
  Stack<Integer> stack = new Stack();
  while (head != null) {
    stack.push(head.val);
    head = head.next;
  }
  int[] ans = new int[stack.size()];
  for (int i = 0; i < ans.length; i++) {
    ans[i] = stack.pop();
  }
  return ans;
}

思路二:

本題還可以採用遞歸實現

遞歸終止條件是:head.next == null;

遞歸的終止操作是將其加入到 ArrayList 中

ArrayList<Integer> list = new ArrayList<>();
public int[] reversePrint(ListNode head) {
  recur(head);
  int[] ans = new int[list.size()];
  for(int i = 0; i < ans.length; i++) {
    ans[i] = list.get(i);
  }
  return ans;
}
public void recur(ListNode head) {
  if (head == null) return;
  recur(head.next);
  list.add(head.val);
}

7. 重建二叉樹

根據二叉樹遍歷的順序,

前序遍歷:按照 根節點-左子樹-右子樹 遍歷

中序遍歷:按照 左子樹-根節點-右子樹 遍歷

思路:

遞歸終止條件:in_st > in_end 時,說明這個時候已經遍歷完了,直接返回null。

構建 node 節點,確定當前遞歸的 nodeindex 即爲 i

TreeNode node = new TreeNode(preorder[pre_st]);

int i = map.get(preorder[pre_st]);

遞歸遍歷 node 的左子節點,遞歸遍歷 node 的右子節點。

最後返回 node

複雜度: 時間複雜度:O(n),空間複雜度:O(n)

HashMap<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
  for (int i = 0; i < inorder.length; i++) {
    map.put(inorder[i], i);
  }
  return recur(preorder, 0, 0, inorder.length - 1);
}

public TreeNode recur(int[] preorder, int pre_st, int in_st, int in_end) {
  if (in_st > in_end) {
    return null;
  }
  TreeNode node = new TreeNode(preorder[pre_st]);
  int i = map.get(preorder[pre_st]);
  node.left = recur(preorder, pre_st + 1, in_st, i - 1);
  node.right = recur(preorder, pre_st + i - in_st + 1, i + 1, in_end);
  return node;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章