——寫在前面,複習算法一段時間了,在此記錄一下自己寫過的算法代碼,算是做個總結,供自己以後回顧。
43.字符串相乘
給定兩個以字符串形式表示的非負整數 num1
和 num2
,返回 num1
和 num2
的乘積,它們的乘積也表示爲字符串形式。
示例 1:
輸入: num1 = "2", num2 = "3"
輸出: "6"
示例 2:
輸入: num1 = "123", num2 = "456"
輸出: "56088"
思路:大數相乘,用一個int數組存每一位的相乘數,像小學時學的乘法運算那樣算
class Solution {
public String multiply(String num1, String num2) {
if(num1.equals("0")||num2.equals("0"))
return "0";
int len1 = num1.length();
int len2=num2.length();
int res_len=len1+len2;
int res[]=new int [res_len];
for(int i=len1-1;i>=0;i--){
int n1=num1.charAt(i)-48;
int tmp=0;
for(int j=len2-1;j>=0;j--){
int n2=num2.charAt(j)-48;
res[i+j+1]=n1*n2+res[i+j+1]+tmp;
tmp =res[i+j+1]/10;
res[i+j+1]=res[i+j+1]%10;
}
res[i]+=tmp;
}
StringBuilder sb=new StringBuilder();
int flag=1;
for(int i=0;i<res_len;i++){
if(res[i]==0&&flag==1)
continue;
sb.append(res[i]);
flag=0;
}
return sb.toString();
}
}
322. 零錢兌換
給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1
。
class Solution {
public int coinChange(int[] coins, int amount) {
int size=coins.length;
int dp[]=new int[amount+1];
//0x3F3F3F表示一個很大的數,dp[j]表示找零金額爲j時的最少硬幣數
Arrays.fill(dp,0x3F3F3F);
dp[0]=0;
//遍歷i種硬幣,新的最少硬幣數會覆蓋舊的最少硬幣數
for(int i=0 ;i<size;i++){
for(int j=coins[i];j<=amount;j++){
//如果拿一個coins[i]硬幣,硬幣數就是dp[j-coins[i]]+1,但如果金額爲j-coins[i]不
//能找零,則找零最少硬幣數爲0x3F3F3F+1,則最少硬幣還是dp[j](0x3F3F3F),歸根到底
//還是不能找零
dp[j]=Math.min(dp[j-coins[i]]+1,dp[j]);
}
}
if(dp[amount]==0x3F3F3F)
dp[amount]=-1;
return dp[amount];
}
}
62. 不同路徑
一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記爲“Start” )。
機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記爲“Finish”)。
問總共有多少條不同的路徑?
輸入: m = 3, n = 2
輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
考察:dp動態規劃,dp[i][j]=dp[i-1][j]+dp[i][j-1]
class Solution {
public int uniquePaths(int m, int n) {
if(m==1&&n==1)
return 1;
int dp[][]=new int[m][n];
for(int i=1;i<n;i++){ //行數爲1,只能橫着走,走法只有一種
dp[0][i]=1;
}
for(int j=1;j<m;j++){ //列數爲1,只能豎着走,走法只有一種
dp[j][0]=1;
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=dp[i-1][j]+dp[i][j-1]; //要麼從上面下來,要麼從左邊過來,走法爲這兩種情況之和
}
}
return dp[m-1][n-1];
}
}
69. x 的平方根
實現 int sqrt(int x)
函數。
計算並返回 x 的平方根,其中 x 是非負整數。
由於返回類型是整數,結果只保留整數的部分,小數部分將被捨去。
示例 2:
輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842...,
由於返回類型是整數,小數部分將被捨去。
考察:二分搜索
class Solution {
public int mySqrt(int x) {
int i=1,j=x;
while(i<=j)
{
int mid=(i+j)/2;
if(mid<x/mid)
i=mid+1;
else if(mid>x/mid)
j=mid-1;
else return mid;
}
return j;
}
}
//另一種做法 return (int)Math.sqrt(x);
94. 二叉樹的中序遍歷
給定一個二叉樹,返回它的中序 遍歷。
示例:
輸入: [1,null,2,3]
1
\
2
/
3
輸出: [1,3,2]
考察:有兩種做法,遞歸很簡單,迭代複雜點
class Solution {
List<Integer> res=new ArrayList<Integer>();
public void search(TreeNode root){ //這是遞歸做法
if(root==null)
return;
if(root.left!=null)
search(root.left);
res.add(root.val);
if(root.right!=null)
search(root.right);
}
public List<Integer> inorderTraversal(TreeNode root) {
search(root);
return res;
}
}
67. 二進制求和
給定兩個二進制字符串,返回他們的和(用二進制表示)。
輸入爲非空字符串且只包含數字 1
和 0
。
示例 1:
輸入: a = "11", b = "1"
輸出: "100"
考察:math,相加的進位
class Solution {
public String addBinary(String a, String b) {
int aLen=a.length()-1;
int bLen=b.length()-1;
int m=0;
int n=0;
StringBuilder res=new StringBuilder();//用數組來存結果也可以,然後把數組轉化爲String,最後如果有進位則在結果前加個"1"
while(aLen>=0&&bLen>=0){
int tmp=a.charAt(aLen)-'0'+b.charAt(bLen)-'0'+n;
m=tmp%2;
n=tmp/2;
res.insert(0,String.valueOf(m));
aLen--;
bLen--;
}
while(aLen>=0){
int tmp=a.charAt(aLen)-'0'+n;
m=tmp%2;
n=tmp/2;
res.insert(0,String.valueOf(m));
aLen--;
}
while(bLen>=0){
int tmp=b.charAt(bLen)-'0'+n;
m=tmp%2;
n=tmp/2;
res.insert(0,String.valueOf(m));
bLen--;
}
if(n>0){
res.insert(0,"1");
}
return res.toString();
}
}
49. 字母異位詞分組
給定一個字符串數組,將字母異位詞組合在一起。字母異位詞指字母相同,但排列不同的字符串。
示例:
輸入: ["eat", "tea", "tan", "ate", "nat", "bat"]
,
輸出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
考察:HashMap
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>>map=new HashMap<>();
List<List<String>>result=new ArrayList<>();
if(strs.length==0)
return result;
for(String s:strs){
char[] tmp=s.toCharArray();
Arrays.sort(tmp);
String keyStr=new String(tmp);
if(!map.containsKey(keyStr))
{
List<String> item=new ArrayList<String>();
item.add(s);
map.put(keyStr,item);
result.add(item);
}
else
map.get(keyStr).add(s);
}
return result;
}
}
206. 反轉鏈表
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
考察:遞推遍歷鏈表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null)
return null;
ListNode cur=head.next;
ListNode next;
head.next=null;
while(cur!=null){
next=cur.next;
cur.next=head;
head=cur;
cur=next;
}
return head;
}
}
23. 合併K個排序鏈表
合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。
示例:
輸入:
[
1->4->5,
1->3->4,
2->6
]
輸出: 1->1->2->3->4->4->5->6
考察:兩指針,歸併
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoList(ListNode first,ListNode two){
if(first==null)
return two;
if(two==null)
return first;
ListNode node=new ListNode(0);
if(first.val<two.val){
node.val=first.val;
node.next=mergeTwoList(first.next,two);
}
else{
node.val=two.val;
node.next=mergeTwoList(first,two.next);
}
return node;
}
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null||lists.length==0)
return null;
else if(lists.length==1)
return lists[0];
else{
int begin=0,end=lists.length-1;
while(end>0){
begin=0;
while(begin<end){
lists[begin]=mergeTwoList(lists[begin],lists[end]);
begin++;
end--;
}
}
return lists[0];
}
}
}
24. 兩兩交換鏈表中的節點
給定一個鏈表,兩兩交換其中相鄰的節點,並返回交換後的鏈表。
示例:
給定1->2->3->4
, 你應該返回2->1->4->3
.
考察:鏈表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null||head.next==null)
return head;
ListNode second=head.next;
ListNode third=second.next;
second.next=head;
head.next=swapPairs(third);
return second;
}
}
98、驗證是否是二叉搜索樹:給定一個二叉樹,判斷其是否是一個有效的二叉搜索樹。
考察:二叉搜索樹的中序遍歷是遞增(或遞減)的,通過遞歸進行中序遍歷
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
boolean isFirst=true;
int lastval;
public boolean isValidBST(TreeNode root) {
if(root ==null){
return true;
}
if(!isValidBST(root.left)){
return false;
}
if(!isFirst&&lastval>=root.val)
return false;
isFirst=false;
lastval=root.val;
if(!isValidBST(root.right)){
return false;
}
return true;
}
}
22. 括號生成
給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果爲:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
考察:深度優先搜索(dfs),棧,括號匹配
class Solution {
int left,right; //分別記錄'('和')'的剩餘數量
LinkedList <Character> stack=new LinkedList<>(); //棧,存儲左括號'('
char item[]; //記錄每種情況的括號排列
int len;
List<String> result=new LinkedList<>();
public void dfs(int depth){
if(depth==len-1){ //遍歷到最後一個括號,一定是')'
item[len-1]=')';
String tmp=new String(item);
result.add(tmp);
}
else {
if(left!=0){
stack.addFirst('(');
item[depth]='(';
left--;
dfs(depth+1);
left++;//回溯
stack.poll();
}
if(right!=0&&!stack.isEmpty()){ //當')'剩餘數不爲0且棧中有'('時,可以取出一個左括號匹配
stack.poll();
item[depth]=')';
right--;
dfs(depth+1);
right++; //回溯
stack.addFirst('(');
}
}
}
public List<String> generateParenthesis(int n) {
left=n-1;
right=n;
len=2*n;
item=new char[n*2];
item[0]='(';
stack.addFirst('(');
dfs(1);
return result;
}
}
127. 單詞接龍
給定兩個單詞(beginWord 和 endWord)和一個字典,找到從 beginWord 到 endWord 的最短轉換序列的長度。轉換需遵循如下規則:
- 每次轉換隻能改變一個字母。
- 轉換過程中的中間單詞必須是字典中的單詞。
說明:
- 如果不存在這樣的轉換序列,返回 0。
- 所有單詞具有相同的長度。
- 所有單詞只由小寫字母組成。
- 字典中不存在重複的單詞。
- 你可以假設 beginWord 和 endWord 是非空的,且二者不相同。
考察:廣度優先搜索,最短路徑,注意:set的查找速度比list快很多
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
if(!wordList.contains(endWord))
return 0;
int level=1,curnum=1,nextnum=0;
LinkedList<String>q=new LinkedList<String>();
Set<String>visited=new HashSet<String>();
q.add(beginWord);
visited.add(beginWord);
Set dic=new HashSet(wordList);
while(!q.isEmpty()){
String str=q.poll();
curnum--;
int len=str.length();
for(int i=0;i<len;i++){
char[]word=str.toCharArray();
for(char j='a';j<='z';j++){
word[i]=j;
String tmp=new String(word);
if(tmp.equals(endWord)){
return level+1;
}
if(dic.contains(tmp)&&!visited.contains(tmp)){
q.add(tmp);
nextnum++;
visited.add(tmp);
}
}
}
if(curnum==0){
level++;
curnum=nextnum;
nextnum=0;
}
}
return 0;
}
}
12、實現strStr():
給定一個 haystack 字符串和一個 needle 字符串,在 haystack 字符串中找出 needle 字符串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。
考察:KMP算法
class Solution {
public int strStr(String haystack, String needle) {
char []nee=needle.toCharArray();
char []hay=haystack.toCharArray();
int l1=hay.length;
int l2=nee.length;
if(l2==0)
return 0;
int next[]=new int[l2];
next[0]=-1;//計算next[]數組,當沒有公共前後綴時,next[i]=-1;
for(int i=1;i<l2;i++){
int t=next[i-1];
while(nee[t+1]!=nee[i]&&t>=0)
t=next[t];
if(nee[t+1]==nee[i])
next[i]=t+1;
else
next[i]=-1;
}
int i=0,j=0;//遍歷查找,時間複雜度爲m+n
while(i<l1){
if(hay[i]==nee[j]){
i++;j++;
if(j==l2)
return i-l2;
}
else{
if(j==0)
i++;
else{
j=next[j-1]+1;
}
}
}
return -1;
}
}
12. 整數轉羅馬數字
羅馬數字包含以下七種字符: I
, V
, X
, L
,C
,D
和 M
。
例如, 羅馬數字 2 寫做 II
,即爲兩個並列的 1。12 寫做 XII
,即爲 X
+ II
。 27 寫做 XXVII
, 即爲 XX
+ V
+ II
。
給定一個整數,將其轉爲羅馬數字。輸入確保在 1 到 3999 的範圍內。
考察:二維數組,math,指針遍歷字符串。
class Solution {
public String intToRoman(int num) {
String str=String.valueOf(num);
String [][] arr={{"I","II","III","IV","V","VI","VII","VIII","IX"},
{"X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},
{"C","CC","CCC","CD","D","DC","DCC","DCCC","CM"},
{"M","MM","MMM"}
};
int len=str.length();
StringBuilder sb=new StringBuilder();
for(int i=0;i<len;i++){
int tmp=str.charAt(i)-'0';
String out;
if(tmp==0)
continue;
if(len-i==4){
out=arr[3][tmp-1];
sb.append(out);
}
else if(len-i==3){
out=arr[2][tmp-1];
sb.append(out);
}
else if(len-i==2){
out=arr[1][tmp-1];
sb.append(out);
}
else{
sb.append(arr[0][tmp-1]);
}
}
return sb.toString();
}
}
13. 羅馬數字轉整數
羅馬數字包含以下七種字符:I
, V
, X
, L
,C
,D
和 M
。
給定一個羅馬數字,將其轉換成整數。輸入確保在 1 到 3999 的範圍內。
考察:swich分支,math
class Solution {
public int romanToInt(String s) {
int index[]={1,5,10,50,100,500,1000};
char[] arr=s.toCharArray();
int len=arr.length;
int last=index[getIndex(arr[0])];
int result=0;
if(len==1)
return last;
int tmp=0;
for(int i=1;i<len;i++){
tmp=index[getIndex(arr[i])];
if(last<tmp)
result-=last;
else result+=last;
last=tmp;
}
result+=tmp;
return result;
}
public int getIndex(char x){
switch(x){
case 'I' :return 0;
case 'V' :return 1;
case 'X' :return 2;
case 'L' :return 3;
case 'C' :return 4;
case 'D' :return 5;
case 'M' :return 6;
default: return -1;
}
}
}
125. 驗證迴文串
給定一個字符串,驗證它是否是迴文串,只考慮字母和數字字符,可以忽略字母的大小寫。
考察:兩指針
class Solution {
public boolean isPalindrome(String s) {
if(s==null||s.length()==0)
return true;
s=s.toLowerCase();
int len=s.length();
char[] arr=new char[len];
int j=0;
for(int i=0;i<len;i++){
char tmp=s.charAt(i);
if(tmp>='a'&&tmp<='z'||tmp>='0'&&tmp<='9')
arr[j++]=tmp;
}
int low=0,high=j-1;
while(low<high){
if(arr[low]==arr[high])
{
low++;
high--;
}
else
return false;
}
return true;
}
}
88. 合併兩個有序數組
給定兩個有序整數數組 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成爲一個有序數組。
考察:兩指針,歸併,歸併排序的歸併部分思路
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int []asis=new int[m];//輔助數組,把nums1中的m個數拷貝出來
for(int i=0;i<m;i++){
asis[i]=nums1[i];
}
int a=0,b=0;//a,b爲兩個指向nums1和nums2開頭的指針
int i=0;
while(i<m+n){
if(a==m)//nums1中沒數據了
nums1[i++]=nums2[b++];
else if(b==n) //nums2中沒數據了
nums1[i++]=asis[a++];
else if(asis[a]<nums2[b]){
nums1[i++]=asis[a++]; //nums1的數比nums2的數小
}
else {
nums1[i++]=nums2[b++]; //nums2的數小
}
}
}
}
73、矩陣置零
給定一個 m x n 的矩陣,如果一個元素爲 0,則將其所在行和列的所有元素都設爲 0。請使用原地算法。
考察:數組,先標記再最後置零
class Solution {
public void setZeroes(int[][] matrix) {
int rlen=matrix.length;
int clen=matrix[0].length;
boolean row[]=new boolean[rlen];
boolean col[]=new boolean[clen];
for(int i=0;i<rlen;i++){
for(int j=0;j<clen;j++){
if(matrix[i][j]==0){
row[i]=true;
col[j]=true;
}
}
}
for(int i=0;i<rlen;i++){
for(int j=0;j<clen;j++){
if(row[i]||col[j])
matrix[i][j]=0;
}
}
}
}
27. 移除元素
給定一個數組 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後數組的新長度。
考察:快排中swap的部分
class Solution {
public int removeElement(int[] nums, int val) {
int len=nums.length;
int right=len-1;
int i=0;
while(i<=right){
if(nums[i]==val){
nums[i]=nums[right--];
}
else i++;
}
return right+1;
}
}
16、有效的數字:
驗證給定的字符串是否爲數字。
例如:"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
考察:math,一個數字是否合法,指針遍歷字符串,細節
class Solution {
public boolean isNumber(String s) {
s=s.trim();
int len=s.length();
if(len==0||s==null)
return false;
int i=0;
boolean hasDot=false;
boolean hasE=false;
boolean hasDigit=false;
if(s.charAt(i)=='e'||s.charAt(len-1)=='e'||s.charAt(len-1)=='+'||s.charAt(len-1)=='-')
return false;
if(s.charAt(i)=='-'||s.charAt(i)=='+'){
i++;
}
while(i<len){
if(s.charAt(i)>='0'&&s.charAt(i)<='9'){
i++;
hasDigit=true;
}
else if(s.charAt(i)=='e'&&hasE==false&&hasDigit==true){
i++;
hasE=true;
if(s.charAt(i)=='+'||s.charAt(i)=='-'){
i++;
}
}
else if(s.charAt(i)=='.'&&hasDot==false&&hasE==false){
i++;
hasDot=true;
}
else return false;
}
if(hasDigit==false)
return false;
return true;
}
}
1、給定一個沒有重複數字的序列,返回其所有可能的全排列。
考察:深度優先搜索(dfs)
class Solution {
int []visit;
List<List<Integer>> result;
int len;
int [] Allnums;
int [] result_arr;
void dfs(int depth){
if(depth==len){
List <Integer> item=new ArrayList<>();
int arrLen=result_arr.length;
for(int j=0;j<arrLen;j++){
item.add(result_arr[j]);
}
result.add(item);
}
else{
for(int i=0;i<len;i++){
if(visit[i]==0){
result_arr[depth]=Allnums[i];
visit[i]=1;
dfs(depth+1);
visit[i]=0;
}
}
}
}
public List<List<Integer>> permute(int[] nums) {
Allnums=nums;
result=new ArrayList<>();
len=nums.length;
result_arr=new int[len];
visit=new int[len];
dfs(0);
return result;
}
}
2、給定一個可包含重複數字的序列,返回所有不重複的全排列。
考察:深度優先搜索(dfs)
class Solution {
int [] input;
int len;
int [] result;
List <List<Integer>> output;
Map<Integer, Integer> map;
Set<Integer> set;
int keylen;
void dfs(int depth){
if(depth==len){
List<Integer> AddToOutput=new ArrayList<Integer>();
for(int k=0;k<len;k++){
AddToOutput.add(result[k]);
}
output.add(AddToOutput);
return;
}
for(int i=0;i<keylen;i++){
int value=map.get(input[i]);
if(value>=1){
result[depth]=input[i];
map.put(input[i], value-1);
dfs(depth+1);
map.put(input[i], value);
}
}
}
public List<List<Integer>> permuteUnique(int[] nums) {
len=nums.length;
map=new HashMap<Integer, Integer>();
for(int i=0;i<len;i++){
if(map.get(nums[i])==null){
map.put(nums[i], 1);
}
else{
int tmp=map.get(nums[i]);
map.put(nums[i],tmp+1);
}
}
set=map.keySet();
keylen=set.size();
input=new int[keylen];
Iterator<Integer>it=set.iterator();
int cnt=0;
while(it.hasNext()){
input[cnt++]=it.next();
}
result=new int[len];
output=new ArrayList<>();
dfs(0);
return output;
}
}
3、求最大子序和:給定一個整數數組 nums
,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
考察:動態規劃
class Solution {
public int maxSubArray(int[] nums) {
int len=nums.length;
int []sum=new int[len];
int []maxsubsum=new int[len];
sum[0]=nums[0];
maxsubsum[0]=nums[0];
for(int i=1;i<len;i++){
if(sum[i-1]<0)
sum[i]=nums[i];
else{
sum[i]=sum[i-1]+nums[i];
}
}
for(int i=1;i<len;i++){
maxsubsum[i]=Math.max(maxsubsum[i-1],sum[i]);
}
return maxsubsum[len-1];
}
}
5、二叉樹的層次遍歷
考察:廣度優先搜索(bfs)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
LinkedList <TreeNode> q=new LinkedList<TreeNode>();
List <List<Integer>> result=new LinkedList<>();
if(root==null)
return result;
List <Integer> first=new LinkedList<Integer>();
first.add(root.val);
result.add(first);
q.offer(root);
int curnum=1;
int nextnum=0;
List <Integer> item=new LinkedList<Integer>();
while(!q.isEmpty()){
TreeNode t=q.poll();
curnum--;
if(t.left!=null){
item.add(t.left.val);
q.offer(t.left);
nextnum++;
}
if(t.right!=null){
item.add(t.right.val);
q.offer(t.right);
nextnum++;
}
if(curnum==0){
curnum=nextnum;
nextnum=0;
if(!item.isEmpty())
{
result.add(item);
item=new LinkedList<Integer>();
}
}
}
return result;
}
}
6、合併區間:給出一個區間的集合,請合併所有重疊的區間
考察:排序(快速排序),歸併思路
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
class Solution {
public void quickSort(Interval[] input,int low,int high){
if(low>=high)
return ;
int v=input[low].start;
int left=low,right=high;
int i=low+1;
while(i<=right){
int tmp=input[i].start;
if(tmp>v){
Interval tmp2=input[i];
input[i]=input[right];
input[right--]=tmp2;
}
else if(tmp<v){
Interval tmp2=input[i];
input[i]=input[left];
input[left++]=tmp2;
}
else i++;
}
quickSort(input,low,left-1);
quickSort(input,right+1,high);
}
public List<Interval> merge(List<Interval> intervals) {
List<Interval> res=new ArrayList<Interval>();
int len=intervals.size();
if(len==0)
return res;
Interval [] input= new Interval[len];
intervals.toArray(input);
quickSort(input,0,len-1);
Interval item=input[0];
for(int i=1;i<input.length;i++){
Interval tmp=input[i];
if(tmp.start>item.end)
{
res.add(item);
item=tmp;
}
else{
item.end=Math.max(item.end, tmp.end);
}
}
res.add(item);
return res;
}
}
7、插入區間:
給出一個無重疊的 ,按照區間起始端點排序的區間列表。
在列表中插入一個新的區間,你需要確保列表中的區間仍然有序且不重疊(如果有必要的話,可以合併區間)。
考察:歸併思路
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
class Solution {
public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
List<Interval> res=new ArrayList<Interval>();
int len=intervals.size();
if(len==0){
res.add(newInterval);
return res;
}
int l=newInterval.start;
int r=newInterval.end;
boolean insert=false;
for(int i=0;i<len;i++){
Interval tmp=intervals.get(i);
if(tmp.start<=l&&tmp.end>=l)
l=tmp.start;
if(tmp.start<=r&&tmp.end>=r)
{
r=tmp.end;
continue;
}
if(tmp.start>r&&!insert){
res.add(new Interval(l,r));
insert=true;
}
if(tmp.start>r||tmp.end<l)
res.add(tmp);
}
if(!insert)
res.add(new Interval(l,r));
return res;
}
}
8、無重複字符的最大字串:給定一個字符串,找出不含有重複字符的最長子串的長度
考察:哈希,ascii
class Solution {
public int lengthOfLongestSubstring(String s) {
int [] hash=new int[256];
Arrays.fill(hash, -1);
int maxLen=0,left=-1;
int len=s.length();
for(int i=0;i<len;i++){
left=Math.max(left, hash[s.charAt(i)]);
hash[s.charAt(i)]=i;
maxLen=Math.max(maxLen, i-left);
}
return maxLen;
}
}
9、字符串轉整數:實現 atoi
,將字符串轉爲整數。
考察:指針遍歷字符串的每個字符,math
class Solution {
public int myAtoi(String str) {
if(str.isEmpty())
return 0;
int flag=1,result=0,i=0,len=str.length();
while(i<len&&str.charAt(i)==' ') i++;
if(str.charAt(i)=='+'||str.charAt(i)=='-')
flag=(str.charAt(i++)=='+')?1:-1;
while(i<len&&str.charAt(i)>='0'&&str.charAt(i)<='9'){
if(result>Integer.MAX_VALUE/10||(result==Integer.MAX_VALUE/10&&str.charAt(i)>'7'))
return (flag==1)?Integer.MAX_VALUE:Integer.MIN_VALUE;
result=result*10+(str.charAt(i++)-'0');
}
return flag*result;
}
}
10、三數之和:
給定一個包含 n 個整數的數組 nums
,判斷 nums
中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
考察:2個指針設定,排序
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>>result=new LinkedList<>();
int len=nums.length;
Arrays.sort(nums);
for(int i=0;i<len-2;i++){
if(i>0&&nums[i]==nums[i-1])
continue;
int a=nums[i];
int left=i+1;
int right=len-1;
while(left<right){
if(left>i+1&&nums[left]==nums[left-1])
left++;
else if(a+nums[left]+nums[right]>0){
right--;
}
else if(a+nums[left]+nums[right]<0){
left++;
}
else{
List<Integer>item=new LinkedList<>();
item.add(nums[i]);
item.add(nums[left]);
item.add(nums[right]);
result.add(item);
left++;
right--;
}
}
}
return result;
}
}
11、有效的括號:
給定一個只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判斷字符串是否有效。
考察:棧
class Solution {
public boolean isValid(String s) {
LinkedList<Character> stack=new LinkedList<Character>();
int len=s.length();
for(int i=0;i<len;i++){
Character c=s.charAt(i);
if(c=='('||c=='{'||c=='['){
stack.addFirst(c);
}
else{
if(stack.isEmpty())
return false;
Character top=stack.poll();
if((c==')'&&top!='(')||(c=='}'&&top!='{')||(c==']'&&top!='['))
return false;
}
}
return stack.isEmpty();
}
}
13、合併兩個有序鏈表:
將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
考察:遞歸,歸併思路
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode res=new ListNode(0);
if(l1==null&&l2==null)
return null;
else if(l1!=null&&l2!=null){
if(l1.val<l2.val){
res.val=l1.val;
res.next=mergeTwoLists(l1.next,l2);
}
else {
res.val=l2.val;
res.next=mergeTwoLists(l1,l2.next);
}
}
else if(l1==null&&l2!=null){
res.val=l2.val;
res.next=l2.next;
}
else{
res.val=l1.val;
res.next=l1.next;
}
return res;
}
}
2、兩數相加:
給定兩個非空鏈表來表示兩個非負整數。位數按照逆序方式存儲,它們的每個節點只存儲單個數字。將兩數相加返回一個新的鏈表。
你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。
示例:
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
考察:遞歸
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode add(ListNode l1,ListNode l2,int jin){
if(l1==null&&l2==null&&jin==0)
return null;
if(l1==null)
l1=new ListNode(0);
if(l2==null)
l2=new ListNode(0);
ListNode res=new ListNode(0);
int sum=l1.val+l2.val+jin;
res.val=sum%10;
res.next=add(l1.next,l2.next,sum/10);
return res;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return add(l1,l2,0);
}
}
15、Pow(x,n):
實現 pow(x, n) ,即計算 x 的 n 次冪函數。
考察:分治,把線性複雜度將爲logn
class Solution {
public double myPow(double x, int n) {
double res=1.0;
if(x==0)
return 0;
else if(n==-1)
return 1.0/x;
else if(n==1)
return x;
else if(n==0)
return 1.0;
else {
for(int i=n;i!=0;i/=2,x*=x){
if(i%2!=0)
res*=x;
}
return n<0?1.0/res:res;
}
}
}