劍指offer
時隔一年重新開始劍指offer,爭取月底之前做完劍指吧,做個小記錄。
Easy
- 03 數組中的重複數字
可以用HashMap,比較簡單,在評論區看到一種比較好的辦法,記錄一下
public int findRepeatNumber(int[] nums) {
int n = nums.length;
for (int i = 0;i < n;i ++){
int cur = nums[i];
if(cur < 0){
cur = cur + n;
}
if(nums[cur]<0){
return cur;
}
nums[i] = nums[i] - n;
}
return -1;
}
- 05 替換空格
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()){
if(c==' ') {
sb.append("%20");
}else{
sb.append(c);
}
}
return sb.toString();
}
- 06 從尾到頭打印鏈表
用棧就行了
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<>();
int count = 0;
while (head!=null) {
stack.push(head);
head = head.next;
count++;
}
int[] result = new int[count];
count = 0;
while (!stack.isEmpty()) {
result[count++] = stack.pop().val;
}
return result;
}
- 09 用兩個棧實現隊列
class CQueue {
/**
* 前
* */
private Stack<Integer> s1;
/**
* 後
* */
private Stack<Integer> s2;
public CQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void appendTail(int value) {
s2.push(value);
}
public int deleteHead() {
if (!s1.isEmpty()){
return s1.pop();
}
while(!s2.isEmpty())
{
s1.push(s2.pop());
}
return s1.isEmpty()?-1:s1.pop();
}
}
- 10 斐波拉契
簡單dp
public static int fib(int n) {
if(n<=1)
{
return n;
}
int[] nums = new int[n+1];
nums[0] = 0;
nums[1] = 1;
for (int i = 2;i <= n;i++)
{
nums[i] = nums[i-1]+nums[i-2];
}
return nums[n];
}
- 11 青蛙跳臺階
和上面類似
public static int numWays(int n) {
if(n==0||n==1)
{
return 1;
}
int[] v = new int[n+1];
v[0] = 1;
v[1] = 1;
v[2] = 2;
for (int i = 3;i <= n ;i++)
{
v[i] = (v[i-1]+v[i-2])%(1000000007);
}
return v[n];
}
- 11 旋轉數組的最小數字
轉爲二分查找比較合適,但是需要變通一下。
public static int minArray(int[] numbers) {
int left = 0;
int right = numbers.length-1;
int mid;
if(numbers[left]<numbers[right])
{
return numbers[left];
}
while (left<right)
{
if(numbers[left]<numbers[right])
{
return numbers[left];
}
mid = left + (right - left) / 2;
if(numbers[mid] < numbers[right])
{
right = mid;
}
else if(numbers[mid] > numbers[right])
{
left = mid + 1;
}
else
{
right--;
}
}
return numbers[left];
}
- 15 二進制中1的個數
第一種辦法,比較容易想到,模擬我們手動求數字二進制形式的過程即可,不斷取2的模,然後計數,但需要注意的是,這裏n是無符號數,最高位不做符號位,而是數字位,那麼符號右移的時候,需要採用java的>>>來進行運算,因爲對於有符號的右移,n爲負數的時候,最高位會補1,反之補0,但這裏n是無符號數,所以這裏只能採取無符號右移,也就是默認補0,此外,對於循環的終止條件,不應該用n>0,因爲n可能爲負數。
public int hammingWeight(int n) {
int count = 0;
int num = n;
while (num != 0 ){
int t = num & 1;
count = count + t;
num = num >>> 1;
}
return count;
}
第二種辦法比較巧,相比於第一種辦法突出的地方在於,循環次數減少,因爲這裏我們只需要計算1的個數,而其餘位數的0我們並不在乎,所以可以用n&(n-1)來消去最右邊的1,這樣循環次數就變成了1的個數。
public static int hammingWeight(int n) {
int count = 0;
int num = n;
while (num != 0 ){
int t = num & 1;
count = count + t;
num = num >>> 1;
}
return count;
}