由於是初學者,實現的方法都很簡單,暫時不考慮效率,之後(可能)會更新
1. A+B問題
給出兩個整數 aa 和 bb , 求他們的和。
樣例
如果 a=1 並且 b=2,返回3。
挑戰
顯然你可以直接 return a + b,但是你是否可以挑戰一下不這樣做?(不使用++等算數運算符)
說明
a和b都是 32位 整數麼?
是的
我可以使用位運算符麼?
當然可以
注意事項
你不需要從輸入流讀入數據,只需要根據aplusb的兩個參數a和b,計算他們的和並返回就行。
思路
考慮進位即可
public class Solution {
/**
* @param a: An integer
* @param b: An integer
* @return: The sum of a and b
*/
public int aplusb(int a, int b) {
// write your code here
if (a == 0){return b;}
if (b == 0){return a;}
int sum, add;
sum = a ^ b;
add = (a & b) << 1;
return aplusb(add,sum);
}
}
2. 尾部的零
設計一個算法,計算出n階乘中尾部零的個數
樣例
11! = 39916800,因此應該返回 2
挑戰
O(logN)的時間複雜度
思路
public class Solution {
/*
* @param n: An integer
* @return: An integer, denote the number of trailing zeros in n!
*/
public long trailingZeros(long n) {
// write your code here, try to do it without arithmetic operators.
long count = 0L;
while(n > 0){
count = (long) (count + (Math.floor(n / 5)));
n = (long) Math.floor(n / 5);
}
return count;
}
}
6. 合併排序數組 II
合併兩個排序的整數數組A和B變成一個新的數組。
樣例
給出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6]
挑戰
你能否優化你的算法,如果其中一個數組很大而另一個數組很小?
思路
兩個指針,每次比較兩個數組指針指向元素的大小,小的元素加入新數組,指針後移一位,直到一個數組指針到末尾,另一個數組全部加入新數組。
public class Solution {
/**
* @param A: sorted integer array A
* @param B: sorted integer array B
* @return: A new sorted integer array
*/
public int[] mergeSortedArray(int[] A, int[] B) {
// write your code here
int i = 0;
int j = 0;
List<Integer> result = new ArrayList<Integer>();
while(true){
if(i < A.length && j < B.length){
if(A[i] < B[j]){
result.add(A[i]);
i++;
}else{
result.add(B[j]);
j++;
}
}else{
if (i == A.length){
for(int m = j;m < B.length;m++){
result.add(B[m]);
}
break;
}else{
for(int n = i;n < A.length;n++){
result.add(A[n]);
}
break;
}
}
}
int[] re = new int[result.size()];
for(int k = 0;k < result.size();k++){
re[k] = result.get(k);
}
return re;
}
}
8. 旋轉字符串
給定一個字符串和一個偏移量,根據偏移量旋轉字符串(從左向右旋轉)
樣例
對於字符串 “abcdefg”.
offset=0 => “abcdefg”
offset=1 => “gabcdef”
offset=2 => “fgabcde”
offset=3 => “efgabcd”
挑戰
在數組上原地旋轉,使用O(1)的額外空間
思路
循環取出末尾元素,其餘元素前移一位,取出元素置於首位。(注意數組爲空的情況)
public class Solution {
/**
* @param str: An array of char
* @param offset: An integer
* @return: nothing
*/
public void rotateString(char[] str, int offset) {
// write your code here
if (str.length != 0){
char temp = 'a';
int l = str.length - 1;
int L = str.length;
if (offset > L){
int n = offset / L;
offset -= n * L;
}
while (offset > 0){
offset--;
temp = str[l];
for(int i = 0;i < l;i++){
str[l - i] = str[l - i - 1];
}
str[0] = temp;
}
}
}
}
9. Fizz Buzz 問題
給你一個整數n. 從 1 到 n 按照下面的規則打印每個數:
如果這個數被3整除,打印fizz.
如果這個數被5整除,打印buzz.
如果這個數能同時被3和5整除,打印fizz buzz.
樣例
比如 n = 15, 返回一個字符串數組:
[
“1”, “2”, “fizz”,
“4”, “buzz”, “fizz”,
“7”, “8”, “fizz”,
“buzz”, “11”, “fizz”,
“13”, “14”, “fizz buzz”
]
挑戰
Can you do it with only one if statement?
挑戰參考思路1
思路
依次判斷即可
public class Solution {
/**
* @param n: An integer
* @return: A list of strings.
*/
public List<String> fizzBuzz(int n) {
// write your code here
List<String> result = new ArrayList<String>();
for(int i = 1;i <= n;i++){
if (i % 3 == 0){
if (i % 5 == 0){
result.add("fizz buzz");
}else{
result.add("fizz");
}
}else{
if (i % 5 == 0){
result.add("buzz");
}else{
result.add(""+i);
}
}
}
return result;
}
}
13. 字符串查找
對於一個給定的 source 字符串和一個 target 字符串,你應該在 source 字符串中找出 target 字符串出現的第一個位置(從0開始)。如果不存在,則返回 -1。
樣例
如果 source = “source” 和 target = “target”,返回 -1。
如果 source = “abcdabcdefg” 和 target = “bcd”,返回 1。
挑戰
O(n2)的算法是可以接受的。如果你能用O(n)的算法做出來那更加好。(提示:KMP)
說明
在面試中我是否需要實現KMP算法?
不需要,當這種問題出現在面試中時,面試官很可能只是想要測試一下你的基礎應用能力。當然你需要先跟面試官確認清楚要怎麼實現這個題。
思路
不考慮KMP算法,當每個主串和匹配串首元素相同的時候匹配剩餘字符,不匹配則回到原位置繼續尋找下一個首元素匹配的位置,直到找到,否則返回-1.(注意當主串剩餘長度不足匹配串長度,直接返回-1,否則超出索引報錯)
public class Solution {
/**
* @param source:
* @param target:
* @return: return the index
*/
public int strStr(String source, String target) {
// Write your code here
if(target.equals("")){
return 0;
}else if(source.equals("")){
return -1;
}
int targetLength = target.length();
int i = 0;
while(i < source.length()){
if (source.charAt(i) == target.charAt(0)){
for(int j = 0;j < targetLength;j++){
if (i + j == source.length()){
return -1;
}
if (target.charAt(j) != source.charAt(i+j)){
break;
}else{
if (j == targetLength - 1){
return i;
}
}
}
}
i++;
}
return -1;
}
}
14. 二分查找
給定一個排序的整數數組(升序)和一個要查找的整數target,用O(logn)的時間查找到target第一次出現的下標(從0開始),如果target不存在於數組中,返回-1。
樣例
在數組 [1, 2, 3, 3, 4, 5, 10] 中二分查找3,返回2。
挑戰
如果數組中的整數個數超過了2^32,你的算法是否會出錯?
思路
經典的二分查找即可,注意由於數組有重複項,查到之後要向前遍歷,找到第一個匹配的元素,網上很多方法沒有考慮這個。
public class Solution {
/**
* @param nums: The integer array.
* @param target: Target to find.
* @return: The first position of target. Position starts from 0.
*/
public int binarySearch(int[] nums, int target) {
// write your code here
int begin = 0;
int end = nums.length - 1;
int temp = 0;
if (target == nums[begin]){
return begin;
}
if (target == nums[end]){
return end;
}
if (end - begin < 2){
return -1;
}else{
while(true){
temp = end;
end = (begin + end) / 2;
if(end == begin){
return -1;
}
if(target == nums[end]){
while(true){
if (nums[end - 1] == nums[end]){
end--;
}else{
return end;
}
}
}else if (nums[end] < target){
begin = end;
end = temp;
}
}
}
}
}
22. 平面列表
給定一個列表,該列表中的每個要素要麼是個列表,要麼是整數。將其變成一個只包含整數的簡單列表。
樣例
給定 [1,2,[1,2]],返回 [1,2,1,2]。
給定 [4,[3,[2,[1]]]],返回 [4,3,2,1]。
挑戰
請用非遞歸方法嘗試解答這道題。
注意事項
如果給定的列表中的要素本身也是一個列表,那麼它也可以包含列表。
思路
遞歸對每個元素進行判斷,用好題目所給的接口。
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* public interface NestedInteger {
*
* // @return true if this NestedInteger holds a single integer,
* // rather than a nested list.
* public boolean isInteger();
*
* // @return the single integer that this NestedInteger holds,
* // if it holds a single integer
* // Return null if this NestedInteger holds a nested list
* public Integer getInteger();
*
* // @return the nested list that this NestedInteger holds,
* // if it holds a nested list
* // Return null if this NestedInteger holds a single integer
* public List<NestedInteger> getList();
* }
*/
public class Solution {
private List<Integer> result = new ArrayList<Integer>();
// @param nestedList a list of NestedInteger
// @return a list of integer
public List<Integer> flatten(List<NestedInteger> nestedList) {
// Write your code here
for(int i = 0;i < nestedList.size();i++){
if(nestedList.get(i).isInteger()){
result.add(nestedList.get(i).getInteger());
}else{
flatten(nestedList.get(i).getList());
}
}
return result;
}
}
28. 搜索二維矩陣
寫出一個高效的算法來搜索 m × n矩陣中的值。
這個矩陣具有以下特性:
每行中的整數從左到右是排序的。
每行的第一個數大於上一行的最後一個整數。
樣例
考慮下列矩陣:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
給出 target = 3,返回 true
挑戰
O(log(n) + log(m)) 時間複雜度
思路
因爲矩陣是排好序的,所有通過比對每行第一個數據可以確定目標值所在的行,然後遍歷該行即可
public class Solution {
/**
* @param matrix: matrix, a list of lists of integers
* @param target: An integer
* @return: a boolean, indicate whether matrix contains target
*/
public boolean searchMatrix(int[][] matrix, int target) {
// write your code here
int m = matrix.length;
if(m == 0){
return false;
}
int n = matrix[m - 1].length;
if(n == 0){
return false;
}
if (target < matrix[0][0] || target > matrix[m - 1][n - 1]){
return false;
}else{
int i = 0;
while(i < m && target >= matrix[i][0]){
if(target == matrix[i][0]){
return true;
}
i++;
}
i--;
for(int j = 0;j < matrix[i].length;j++){
if(matrix[i][j] == target){
return true;
}
}
}
return false;
}
}
35. 翻轉鏈表
翻轉一個鏈表
樣例
給出一個鏈表1->2->3->null,這個翻轉後的鏈表爲3->2->1->null
挑戰
在原地一次翻轉完成
思路
遍歷鏈表將所有值取出存在list裏,然後將list值倒序賦值給鏈表的節點
/**
* Definition for ListNode
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* @param head: n
* @return: The new head of reversed linked list.
*/
public ListNode reverse(ListNode head) {
// write your code here
if (head == null){
return null;
}
ListNode currentNode = head;
List<Integer> tempList = new ArrayList<Integer>();
while(currentNode != null){
tempList.add(currentNode.val);
currentNode = currentNode.next;
}
currentNode = head;
int tempListSize = tempList.size();
for(int i = 0;i < tempListSize;i++){
currentNode.val = tempList.get(tempListSize - 1 -i);
currentNode = currentNode.next;
}
return head;
}
}
37. 反轉一個3位整數
反轉一個只有3位數的整數。
樣例
123 反轉之後是 321。
900 反轉之後是 9。
注意事項
你可以假設輸入一定是一個只有三位數的整數,這個整數大於等於100,小於1000。
思路
將每一位依次取出即可
public class Solution {
/**
* @param number: A 3-digit number.
* @return: Reversed number.
*/
public int reverseInteger(int number) {
// write your code here
int a = number / 100;
int b = (number - a * 100 ) / 10;
int c = number - a * 100 - b * 10;
String re_num = "";
re_num = "" + c + b + a ;
int result = Integer.parseInt(re_num);
return result;
}
}
39. 恢復旋轉排序數組
這道題的評判系統有bug,沒有設置[1,1,1,1,1]此類數據,導致代碼可能陷入死循環卻不自知
給定一個旋轉排序數組,在原地恢復其排序。
樣例
[4, 5, 1, 2, 3] -> [1, 2, 3, 4, 5]
挑戰
使用O(1)的額外空間和O(n)時間複雜度
說明
什麼是旋轉數組?
比如,原始數組爲[1,2,3,4], 則其旋轉數組可以是[1,2,3,4], [2,3,4,1], [3,4,1,2], [4,1,2,3]
思路
每次判斷首位元素是否小於等於第二位元素,如果是,則取出放到末尾。也可以判斷首位元素是否大於等於末位元素,如果是,則取出首位放到末位。注意空數組的特殊情況即可。另外注意[1,1,1,1,1]這種所有元素相等的情況,以下代碼加入計數器,當計數器大於數組長度即說明所有元素均相等,退出循環。
public class Solution {
/**
* @param nums: An integer array
* @return: nothing
*/
public void recoverRotatedSortedArray(List<Integer> nums) {
// write your code here
int numsSize = nums.size();
if(numsSize > 0 && nums.get(0) >= nums.get(numsSize - 1)){
int temp = 0;
int count = 0;
while(true){
if(count > numsSize){
break;
}
if(nums.get(0) <= nums.get(1)){
temp = nums.get(0);
nums.remove(0);
nums.add(temp);
count++;
}else{
temp = nums.get(0);
nums.remove(0);
nums.add(temp);
break;
}
}
}
}
}
41. 最大子數組
給定一個整數數組,找到一個具有最大和的子數組,返回其最大和。
樣例
給出數組[−2,2,−3,4,−1,2,1,−5,3],符合要求的子數組爲[4,−1,2,1],其最大和爲6
挑戰
要求時間複雜度爲O(n)
注意事項
子數組最少包含一個數
思路
不考慮時間複雜度,雙層循環,每次從nums[i]開始,一個一個累加,遇到比max大的就賦給max,直到循環結束。
這個題網上很多答案說單層循環,遇到和小於0直接捨棄,但是數組如果所有元素都小於0呢???
補充:由於是先與max比較再捨棄,所以沒有問題
public class Solution {
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
public int maxSubArray(int[] nums) {
// write your code here
int sum;
int max = nums[0];
for(int i = 0;i < nums.length;i++){
sum = 0;
for(int j = 0;j < nums.length - i;j++){
sum = sum + nums[i + j];
if (sum > max){
max = sum;
}
}
}
return max;
}
}
44. 最小子數組
給定一個整數數組,找到一個具有最小和的子數組。返回其最小和。
樣例
給出數組[1, -1, -2, 1],返回 -3
注意事項
子數組最少包含一個數字
思路
與41題一樣,大於號和小於號換一下就行,此處貼出其他人的代碼,原地址:參考代碼
public class Solution {
/*
* @param nums: a list of integers
* @return: A integer indicate the sum of minimum subarray
*/
public int minSubArray(List<Integer> A) {
// write your code here
int min = Integer.MAX_VALUE, sum = 0;
for (int i = 0; i < A.size(); i++) {
sum += A.get(i);
min = Math.min(min, sum);
sum = Math.min(sum, 0);
}
return min;
}
}
145. 大小寫轉換
將一個字符由小寫字母轉換爲大寫字母
樣例
a -> A
b -> B
思路
根據ascii碼,減去32即可
public class Solution {
/**
* @param character: a character
* @return: a character
*/
public char lowercaseToUppercase(char character) {
// write your code here
return (char)((int) character - 32);
}
}
454. 矩陣面積
實現一個矩陣類Rectangle,包含如下的一些成員變量與函數:
兩個共有的成員變量 width 和 height 分別代表寬度和高度。
一個構造函數,接受2個參數 width 和 height 來設定矩陣的寬度和高度。
一個成員函數 getArea,返回這個矩陣的面積。
樣例
Example1:
Java:
Rectangle rec = new Rectangle(3, 4);
rec.getArea(); // should get 12,3*4=12
Python:
rec = Rectangle(3, 4)
rec.getArea()
Example2:
Java:
Rectangle rec = new Rectangle(4, 4);
rec.getArea(); // should get 16,4*4=16
Python:
rec = Rectangle(4, 4)
rec.getArea()
思路
參考各語言教程
public class Rectangle {
/*
* Define two public attributes width and height of type int.
*/
// write your code here
private int width;
private int height;
/*
* Define a constructor which expects two parameters width and height here.
*/
// write your code here
public Rectangle(int width,int height){
this.width = width;
this.height = height;
}
/*
* Define a public method `getArea` which can calculate the area of the
* rectangle and return.
*/
// write your code here
public int getArea(){
return this.width * this.height;
}
}
463. 整數排序
給一組整數,按照升序排序,使用選擇排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法。
樣例
對於數組 [3, 2, 1, 4, 5], 排序後爲:[1, 2, 3, 4, 5]。
思路
冒泡排序
public class Solution {
/**
* @param A: an integer array
* @return: nothing
*/
public void sortIntegers(int[] A) {
// write your code here
int temp;
for(int i = 0;i < A.length;i++){
for(int j = i + 1;j < A.length;j++)
{
if (A[j] < A[i]){
temp = A[j];
A[j] = A[i];
A[i] = temp;
}
}
}
}
}
466. 鏈表節點計數
計算鏈表中有多少個節點.
樣例
給出 1->3->5, 返回 3.
思路
從head開始依次計數,直到next爲null
/**
* Definition for ListNode
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* @param head: the first node of linked list.
* @return: An integer
*/
public int countNodes(ListNode head) {
// write your code here
if(head == null){
return 0;
}
ListNode p = head;
ListNode q = head.next;
int count = 1;
while(q!=null){
count++;
p = q;
q = p.next;
}
return count;
}
}
484. 交換數組兩個元素
略。
632. 二叉樹的最大節點
在二叉樹中尋找值最大的節點並返回。
樣例
給出如下一棵二叉樹:
1
/ \
-5 3
/ \ / \
1 2 -4 -5
返回值爲 3 的節點。
思路
中序遍歷二叉樹,將二叉樹節點的值存入鏈表
/**
* Definition of TreeNode:
* public class TreeNode {
* public int val;
* public TreeNode left, right;
* public TreeNode(int val) {
* this.val = val;
* this.left = this.right = null;
* }
* }
*/
public class Solution {
/*
* @param root: the root of tree
* @return: the max node
*/
public TreeNode maxNode(TreeNode root) {
// Write your code here
TreeNode resultMaxNode = root;
TreeNode currentNode = root;
LinkedList<TreeNode> nodeLink = new LinkedList<TreeNode>();
while(currentNode != null || !nodeLink.isEmpty()){
if(currentNode != null){
nodeLink.push(currentNode);
currentNode = currentNode.left;
}else{
currentNode = nodeLink.pop();
if(currentNode.val > resultMaxNode.val){
resultMaxNode = currentNode;
}
currentNode = currentNode.right;
}
}
return resultMaxNode;
}
}