3、无重复字符的最长字串
方法1、暴力求解
逐个生成子字符串
看它是否不含有重复的字符
方法2、滑动窗口及优化
从a-c都不重复,等到a重复的时候,左指针向右移动一位
右指针向右移动一位
双指针JAVA Code:
class Solution {
public int lengthOfLongestSubstring(String s) {
HashSet<Character> set = new HashSet<>();
int right = -1;
int maxLen = 0;
for(int left=0;left<s.length();left++){
if(left != 0){
set.remove(s.charAt(left-1));
}
while(right+1 < s.length() && !set.contains(s.charAt(right+1))){
set.add(s.charAt(right+1));
right++;
}
maxLen = Math.max(maxLen, right-left+1);
}
return maxLen;
}
}
#####################################################
#####################################################
#####################################################
#####################################################
#####################################################
4、寻找两个正序数组的中位数
JAVA Code:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
if(m > n){
return findMedianSortedArrays(nums2,nums1); //保证m <= n
}
//初始化i的区间,i的最小值是0,最大值是m
int iMin = 0, iMax = m;
while(iMin <= iMax){
int i = (iMin + iMax) / 2; //二分法,取i为区间的中间值
int j = (m + n + 1) / 2 - i; //由i确定j
//交叉比较,判断i是大了还是小了
if(j != 0 && i != m && nums2[j-1]>nums1[i]){ //i需要增大
iMin = i + 1;
}
else if(i != 0 && j != n && nums1[i-1] > nums2[j]){ //i需要减小
iMax = i-1;
}
else{ //达到要求,并且将边界条件列出来单独考虑
int maxLeft = 0;
if(i == 0){maxLeft = nums2[j-1];}
else if(j == 0){maxLeft = nums1[i-1];}
else{maxLeft = Math.max(nums1[i-1],nums2[j-1]);}
if((m+n)%2==1){return maxLeft;} //奇数的话不需要考虑右半部分
//如果(m+n)是偶数,再求右边的最小值
int minRight = 0;
if(i == m){minRight = nums2[j];}
else if(j == n){minRight = nums1[i];}
else{minRight = Math.min(nums2[j],nums1[i]);}
return (maxLeft + minRight)/2.0; //返回左右部分最值的平均值即为中位数
}
}
return 0;
}
}
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
5、最长回文子串
如果i和j指向的两个不同元素,直接向右移动i下标
如果两个指针指向同一个下标,向右移动j下标
然后i下标放回字符串的头部,从头开始扫描
i和j不相等,继续向右移动i下标
动态规划:
1、状态容器:一维数组或二维数组
2、初始化:起始步骤
3、状态转移方程
4、结果
动态规划JAVA Code:
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len <= 1) return s;
//状态容器
boolean[][] dp = new boolean[len][len];
for(int i = 0;i < len;i++){
dp[i][i] = true;
}
int max = 1,start = 0;
for(int j = 1;j < len;j++){
for(int i = 0; i < len-1 && i < j;i++){
if(s.charAt(i) != s.charAt(j)){
dp[i][j] = false;
}else{
if(j-i < 3){
dp[i][j] = true;
}else{
dp[i][j] = dp[i+1][j-1];
}
}
if(dp[i][j] && j-i+1 > max){
max = j-i+1;
start = i;
}
}
}
return s.substring(start,start+max);
}
}
####################################################
####################################################
####################################################
####################################################
####################################################
6、Z字形变换
JAVA Code:
class Solution {
public String convert(String s, int numRows) {
if(numRows <= 1 || s.length() ==1){
return s;
}
int len = s.length();
StringBuilder[] sbd = new StringBuilder[numRows];
for(int i=0;i<numRows;i++){
sbd[i] = new StringBuilder();
}
int T = numRows*2 - 2;
for(int i = 0;i<len;i++){
int j = i%T;
if(j < numRows){
sbd[j].append(s.charAt(i));
}else{
sbd[T-j].append(s.charAt(i));
}
}
for(int i=1;i<numRows;i++){
sbd[0].append(sbd[i]);
}
return sbd[0].toString();
}
}
#################################################
#################################################
#################################################
#################################################
#################################################
8、字符串转换整数
有限状态自动机
状态转移路径
//’'排第0位 ±排第1位 0-9排第2位 .a-Z排第3位
// ‘’ ± 0-9 .a-Z
//0: 0 1 2 3
//1: 3 3 2 3
//2: 3 3 2 3
//3: 3 3 2 3
JAVA Code:
class Solution {
private int sign = 1; //1代表正数 -1代表负数
private long ans = 0;
private String state = "start";
private Map<String,String[]> hashMap = new HashMap<>(){{
put("start",new String[]{"start","sign","number","end"});
put("sign",new String[]{"end","end","number","end"});
put("number",new String[]{"end","end","number","end"});
put("end",new String[]{"end","end","end","end"});
}};
public int myAtoi(String s){
for(int i=0;i<s.length();i++){
get(s.charAt(i));
}
return (int)(sign*ans);
}
public void get(char c){
state = hashMap.get(state)[getCol(c)];
if(state.equals("number")){
ans = 10 * ans +c - '0';
ans = sign == 1 ? Math.min(ans,(long)Integer.MAX_VALUE):Math.min(ans,-(long)Integer.MIN_VALUE);
}else if(state.equals("sign")){
sign = c == '+'?1:-1;
}
}
public int getCol(char c){
if(c == ' '){
return 0;
}else if(c == '+' || c=='-'){
return 1;
}else if(Character.isDigit(c)){
return 2;
}
return 3;
}
}
#############################################################
#############################################################
#############################################################
#############################################################
#############################################################
10、正则表达式配对
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
11、盛最多水的容器
JAVA Code:
超出时间限制----双指针
class Solution {
public int maxArea(int[] height) {
int n = height.length;
int MaxArea = 0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int area = (j-i)*Math.min(height[i],height[j]);
MaxArea = Math.max(area,MaxArea);
}
}
return MaxArea;
}
}
JAVA Code:
左右指针
class Solution {
public int maxArea(int[] height) {
int area = 0;
int l = 0;
int r = height.length - 1;
while(l < r){
int MaxArea = (r - l)*Math.min(height[r],height[l]);
area = Math.max(area,MaxArea);
if(height[l] <= height[r]){
l++;
}else{
r--;
}
}
return area;
}
}
#############################################
#############################################
#############################################
#############################################
#############################################
12.整数转罗马数字
JAVA Code:
class Solution {
public String intToRoman(int num) {
int values[] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
String[] romans = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
StringBuilder sb = new StringBuilder();
for(int i=0;i<values.length;i++){
while(num>=values[i]){
num -= values[i];
sb.append(romans[i]);
}
}
return sb.toString();
}
}
python code:
class Solution:
def intToRoman(self, num: int) -> str:
res = ''
dic = {1000:'M',900:'CM',500:'D',400:'CD',100:'C',90:'XC',50:'L',40:'XL',10:'X',9:'IX',5:'V',4:'IV',1:'I'}
for x in dic:
tmp = num // x
if tmp:
res += dic[x] * tmp
num -= x * tmp
return res
#################################################
#################################################
#################################################
#################################################
#################################################
13、罗马数字转整数
Python Code:
class Solution:
def romanToInt(self, s: str) -> int:
res = 0
dic = {'M':1000,'CM':900,'D':500,'CD':400,'C':100,'XC':90,'L':50,'XL':40,'X':10,'IX':9,'V':5,'IV':4,'I':1}
for x in dic:
while s.startswith(x): #判断字符串是否以指定的前缀开始
res += dic[x]
if len(x) == 1:
s = s[1:]
else:s = s[2:]
return res
#####################################################
#####################################################
#####################################################
#####################################################
#####################################################
14、最长公共前缀
Python Code:
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
res = min(strs)
for s in strs:
for j in range(len(res)):
if( s[j] != res[j]):
res = res[:j]
break
return res
#####################################################
#####################################################
#####################################################
#####################################################
#####################################################
15、三数之和
JAVA Code:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
Set<List<Integer>> res = new HashSet<>();
for(int i=0;i<n;i++){
int l = i+1;
int r = n-1;
while(l<r){
if(nums[i]+nums[l]+nums[r] == 0){
res.add(Arrays.asList(nums[i],nums[l],nums[r]));
l++;
r--;
}else if(nums[i] + nums[l] + nums[r] < 0){
l++;
}else{
r--;
}
}
}
List<List<Integer>> ans = new ArrayList<>();
ans.addAll(res);
return ans;
}
}
16、最接近的三数之和
Python:
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
temp = 2**31-1
for i in range(len(nums)-2):
#双指针
p = i + 1
q = len(nums) - 1
while p < q:
now = nums[i]+nums[p]+nums[q]
if(abs(now - target) < temp):
temp = abs(now - target)
ans = now
if(now > target):
q-=1
if(now < target):
p+=1
if(now == target):
if p < q:
return nums[i]+nums[p]+nums[q]
return ans
####################################################
####################################################
####################################################
####################################################
####################################################
17、电话号码的字母组合
JAVA Code:
class Solution {
List<Character> list = new ArrayList<>();
List<List<Character>> res = new ArrayList<List<Character>>();
HashMap<Character,String> map = new HashMap<>();
public List<String> letterCombinations(String digits) {
List<String> finalres = new ArrayList<String>();
if(digits == null || digits.isEmpty()) return finalres;
map.put('2',"abc");
map.put('3',"def");
map.put('4',"ghi");
map.put('5',"jkl");
map.put('6',"mno");
map.put('7',"pqrs");
map.put('8',"tuv");
map.put('9',"wxyz");
helper(digits,0);
for(int i=0;i<res.size();i++){
List<Character> l =res.get(i);
StringBuilder sb = new StringBuilder();
for(int j=0;j<l.size();j++){
sb.append(l.get(j));
}
finalres.add(sb.toString());
}
return finalres;
}
private void helper(String digits,int start){
if(list.size() == digits.length()){
res.add(new ArrayList<Character>(list));
return;
}
Character digit = digits.charAt(start);
String letters = map.get(digit);
for(int i=0;i<letters.length();i++){
list.add(letters.charAt(i));
helper(digits,start+1);
list.remove(list.size()-1);
}
}
}
##################################
##################################
##################################
##################################
##################################
18、四数之和
JAVA Code:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int n = nums.length;
for(int i=0;i<n-3;i++){
if(i>0 && nums[i]==nums[i-1]){
continue;
}
for(int j = i+1;j<n-2;j++){
if(j>i+1 && nums[j] == nums[j-1]){
continue;
}
//two sum
int t = target - nums[i] - nums[j];
int start = j+1,end=n-1;
while(start<end){
int cur = nums[start]+nums[end];
if(cur<t){
start++;
}else if(cur>t){
end--;
}else{
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[start]);
temp.add(nums[end]);
res.add(temp);
start++;
while(start < end && nums[start] == nums[start-1]){
start++;
}
end--;
while(start < end && nums[end]==nums[end+1]){
end--;
}
}
}
}
}
return res;
}
}
##########################################
##########################################
##########################################
##########################################
##########################################
19、删除链表的倒数第N个结点
JAVA
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1,head);
int len = getLength(head);
ListNode tmp = dummy;
for(int i=1;i<=(len-n);i++){
tmp = tmp.next;
}
tmp.next = tmp.next.next;
return dummy.next;
}
private int getLength(ListNode head){
int res = 0; //获取链表长度
while(head != null){
res++;
head = head.next;
}
return res;
}
}
JAVA
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1,head);
Stack<ListNode> stack = new Stack<>();
ListNode tmp = dummy;
while(tmp != null){
stack.push(tmp);
tmp = tmp.next;
}
for(int i=1;i<=n;i++){
stack.pop();
}
ListNode ans = stack.peek(); //返回栈顶的元素但不移除它
ans.next = ans.next.next;
return dummy.next;
}
}
双指针:JAVA
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1,head);
ListNode first = head;
ListNode second = dummy;
for(int i=1;i<=n;i++){
first=first.next;
}
while(first != null){
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
}
#####################################
#####################################
#####################################
#####################################
#####################################
23、合并K个升序链表
JAVA Code:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode head = null; //不动
ListNode temp = null; //动,往后移
while(true){
int minIndex = -1;//每个数组最小值下标
for(int i=0;i<lists.length;i++){
if(lists[i] != null){
if(minIndex == -1){
minIndex = i;
}else{
if(lists[i].val < lists[minIndex].val){
minIndex = i;
}
}
}
}
if(minIndex == -1){
break; //所有节点都为空
}
if(head == null){
head = lists[minIndex];
temp = head; //初始化
}else{
temp.next = lists[minIndex]; //temp的下一个就是当前遍历的最小值
temp = temp.next; //temp后移,为了下一次循环
}
lists[minIndex] = lists[minIndex].next;
}
return head;
}
}
用堆来解决
JAVA Code:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
private Comparator<ListNode> comparator = new Comparator<ListNode>(){
@Override
public int compare(ListNode o1,ListNode o2){
if(o1.val > o2.val){
return 1;
}else if(o1.val < o2.val){
return -1;
}else{
return 0;
}
}
};
public ListNode mergeKLists(ListNode[] lists) {
ListNode head = null;
ListNode temp = null;
PriorityQueue<ListNode> heap = new PriorityQueue<>(comparator); //堆,每次取最小值
for(int i=0;i<lists.length;i++){
if(lists[i] != null){
heap.offer(lists[i]);
}
}
while(heap.size()>0){
ListNode temp0 = heap.poll(); //弹出最小值
if(head == null){ //初始化
head = temp0;
temp = head;
}else{ //指向下一个
temp.next = temp0;
temp = temp.next; //指向下一个,进入下一次循环
}
if(temp0.next != null){ //heap中扔进去下一个
heap.offer(temp0.next); //将此链表的下一个扔进去
}
}
return head;
}
}
########################################################
########################################################
#########################################################
########################################################
########################################################
25、K个一组翻转链表
Python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
ret_head = ListNode()
tail_head = ret_head
while head:
reversed_head,next_head = self.reversek(head,k)
tail_head.next = reversed_head
tail_head = head
head = next_head
return ret_head.next
def reversek(self,head,k):
if k==1:
return head,None
i=0
pre_head = None
while(head and i < k):
next = head.next
head.next = pre_head
pre_head = head
head = next
i += 1
if i != k:
return self.reversek(pre_head,i)
return pre_head,head
##############################################################3
###############################################################
###############################################################
###############################################################
#################################################################
29、两数相除
Python Code:
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
limit = 2**31
isNeg = (dividend<0)!=(divisor<0)
dividend,divisor = abs(dividend),abs(divisor)
res = 0
div,track = divisor,1
while dividend >= divisor:
while dividend >= (div<<1):
div <<= 1
track <<= 1
res += track
dividend -= div
div,track = divisor,1
return max(-limit,min(limit-1,-res if isNeg else res))
#########################################################
#########################################################
#########################################################
#########################################################
#########################################################
30、串联所有单词的子串
Python Code:
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
n,m,num = len(s),len(words),len(words[0])
ans = []
wordmap = Counter(words) ##返回一个key为列表的值,value为该值的具体个数的对象
for i in range(n-m*num+1):
#s[i:i+n*num] 滑动窗口
j = 0
hashmap = dict()
while j<m:
key = s[i+j*num:i+j*num+num]
if key in wordmap:
hashmap[key]=hashmap[key]+1 if key in hashmap else 1
if hashmap[key] > wordmap[key]:
break
else:
break
j+=1
if j==m:
ans.append(i)
return ans
###########################################################
###########################################################
############################################################
###########################################################
###########################################################
31、下一个排列
Python code:
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if sorted(nums,reverse=True) == nums: #从大到小排序,此为最大值
nums[:] = nums[::-1] #将数组反转
return
for i in range(len(nums)-1)[::-1]: #倒叙 10 9 8 7 6 5 4 3 2 1 0
if nums[i]<nums[i+1]:
break
for j in range(i+1,len(nums)):
if j==len(nums)-1 or nums[j+1]<=nums[i]:
nums[i],nums[j] = nums[j],nums[i]
break
nums[i+1:] = nums[i+1:][::-1]
return
#######################################################
#######################################################
#######################################################
#######################################################
#######################################################
32、最长有效括号
动态规划
JAVA Code:
class Solution {
public int longestValidParentheses(String s) {
int[] dp = new int[s.length()];
Arrays.fill(dp,0);
int max = 0;
for(int i=1;i<s.length();i++){
char c = s.charAt(i);
if(c==')'){
if(i-dp[i-1]>0 && s.charAt(i-dp[i-1]-1)=='('){
dp[i] = 2 + dp[i-1] + (i-dp[i-1]-2>-1 ? dp[i-dp[i-1]-2]:0);
}
}
max = Math.max(max,dp[i]);
}
return max;
}
}
栈+动态规划
class Solution:
def longestValidParentheses(self, s: str) -> int:
N = len(s)
stack = []
dp = [0]*(N+1)
#
for i,ch in enumerate(s):
index = i+1
if ch == '(':
stack.append(ch)
else: #')'
if stack:
stack.pop()
pairs = 1+dp[index-1]
prev_index = index - pairs * 2
if prev_index > 0:
pairs += dp[prev_index]
dp[index] = pairs
return max(dp)*2
##############################################
##############################################
##############################################
##############################################
##############################################
33、搜索旋转排序数组
JAVA Code:
class Solution {
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length - 1;
while(l <= r){
int m = (l+r)/2;
if(nums[m] == target) return m;
else if(nums[m] < target){
if(nums[m] >= nums[0]){
l = m + 1;
}else{
if(target < nums[0]){
l = m + 1;
}else{
r = m - 1;
}
}
}else if(nums[m] > target){
if(nums[m] >= nums[0]){
if(target < nums[0]){
l = m + 1;
}else{
r = m - 1;
}
}else{
r = m - 1;
}
}
}
return -1;
}
}
##################################################
##################################################
##################################################
##################################################
##################################################
34、在排序数组中查找元素的第一个和最后一个位置
二分法JAVA Code:
class Solution {
public int[] searchRange(int[] nums, int target) {
int firstIndex = findFirst(nums,target);
int lastIndex = findFirst(nums,target+1)-1;
if(firstIndex == nums.length || nums[firstIndex] != target){
return new int[]{-1,-1};
}else{
return new int[]{firstIndex,lastIndex};
}
}
//二分查找方法封装 查找target第一次出现的位置
private int findFirst(int[] nums,int target){
//这里high取值要比数组下标最大值大1,因为考虑如果当前target不存在
//于数组中,我们就把它插入到最后一个位置,因为这里我们要找找到target
//最后一次出现的位置,我们的做法是先找到比target大1也就是target+1
//的第一次出现的位置,然后下标减去1就是target最后一次出现的位置
int low = 0,high = nums.length;
while(low <high){
int mid = low + (high - low)/2;
if(nums[mid] >= target){
high = mid;
}else{
low = mid + 1;
}
}
return low;
}
}
##############################################
##############################################
##############################################
##############################################
##############################################
36、有效的数独
暴力法JAVA Code:
class Solution {
public boolean isValidSudoku(char[][] board) {
HashSet<String> set = new HashSet<>();
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
char curr = board[i][j];
if(curr=='.') continue;
int boxIndex = i/3*3 + j/3;
String r = curr + " in row " + i;
String c = curr + " in col " + j;
String b = curr + " in box " + boxIndex;
boolean res = set.add(r) && set.add(c) && set.add(b);
if(!res) return false;
}
}
return true;
}
}
JAVA Code:
class Solution {
public boolean isValidSudoku(char[][] board) {
//HashSet<String> set = new HashSet<>();
boolean[][] row = new boolean[9][9];
boolean[][] col = new boolean[9][9];
boolean[][] box = new boolean[9][9];
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
char curr = board[i][j];
if(curr=='.') continue;
int currIndex = curr - '1'; //index
int boxIndex = i/3*3 + j/3;
if(row[i][currIndex] ||col[j][currIndex] || box[boxIndex][currIndex]) return false;
row[i][currIndex] = true;
col[j][currIndex] = true;
box[boxIndex][currIndex] = true;
}
}
return true;
}
}
###########################################
###########################################
###########################################
###########################################
###########################################
37、解数独