——写在前面,复习算法一段时间了,在此记录一下自己写过的算法代码,算是做个总结,供自己以后回顾。
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;
}
}
}