1 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
滑动窗口法:
定义两个指针,start和end,代表当前窗口的开始和结束位置,使用hashset,当窗口中出现重复的字符时,start++,没有重复时,end++,每次更新长度的最大值
代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null)
return 0;
int res = 0;
int start = 0;
int end = 0;
Set<Character> set = new HashSet<>();
while(start<s.length()&&end<s.length()){
if(set.contains(s.charAt(end))){
set.remove(s.charAt(start++));
}else{
set.add(s.charAt(end++));
res=Math.max(res,end-start);
}
}
return res;
}
}
二 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
startsWith() 方法用于检测字符串是否以指定的前缀开始,使用该方法可以很简单的一次遍历完成查找。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs ==null){
return null;
}
if(strs.length==0){
return "";
}
if(strs.length==1){
return strs[0];
}
String temp = strs[0];
for(int i=1;i<strs.length;i++){
while(!strs[i].startsWith(temp)){
temp = temp.substring(0,temp.length()-1);
}
}
return temp;
}
}
三 两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
这个题直接相应位求和即可,若链表长度不相等,用0补齐
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);
ListNode root = res;
if(l1 == null && l2 ==null){
return res;
}
if(l1 ==null || l2 == null){
return l1==null?l2:l1;
}
int carry = 0;//进位
while(l1 !=null || l2 !=null ||carry != 0){
ListNode temp = new ListNode(0);
int sum = (l1==null?0:l1.val)+(l2==null?0:l2.val)+carry;
temp.val = sum %10;
carry = sum /10;
root.next = temp;
root = temp;
l1=(l1 == null)?l1:l1.next;
l2=(l2 == null)?l2:l2.next;
}
return res.next;
}
}
四 链表排序
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
O(n log n)的时间复杂度的排序方法有快排,堆排,归并,这里只是尝试了一下快排,用时297ms,哈哈
快排的思想可以参照:https://mp.csdn.net/postedit/88769279
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next ==null)
return head;
quickSort(head,null);
return head;
}
public void quickSort(ListNode begin,ListNode end){
if(begin != end){
ListNode pivot = partion(begin,end);
quickSort(begin,pivot);
quickSort(pivot.next,end);
}
}
public ListNode partion(ListNode begin,ListNode end){
ListNode preer = begin;
ListNode pre = preer.next;
ListNode temp = begin;
ListNode curr = begin.next;
while(curr != end){
if(temp.val >curr.val){
int t = pre.val;
pre.val = curr.val;
curr.val = t;
preer = pre;
pre = pre.next;
}
curr = curr.next;
}
if(preer != temp){
int t = preer.val;
preer.val = temp.val;
temp.val = t;
}
return preer;
}
}
五 第k个排列
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例 1:
输入: n = 3, k = 3
输出: "213"
一个比较容易想到的思路就是对给定的n个数求全排列,排序,取第k-1个元素,但这种方法复杂度很高,会超时
class Solution {
int[] arr;
ArrayList<String> list=new ArrayList<>();
public String getPermutation(int n, int k) {
arr = new int[n+1];
for(int i=0;i<n+1;i++){
arr[i] = i+1;
}
fullsort(arr,list,0,n+1);
Collections.sort(list);
return list.get(k-1);
}
public void fullsort(int[] arr,ArrayList<String> list,int start,int end){
while(start<end){
for(int i=start;i<end;i++){
swap(arr,i,start);
list.add(Arrays.toString(arr));
fullsort(arr,list,start+1,end);
swap(arr,i,start);
}
}
}
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
看大佬们代码,发现一种不需全排列就可直接得到第k个排列,主要思路:
1、需要一个list存放1到n的所有数:[1,2,3,...,n]
2、以n,k为例对于每一位上的数字:num = k/(n-1)! 向上取整,把num的值从list中删去
3 重新计算下一次循环的n=n-1,k=k-(num-1)*(n-1)!递归直到list中只剩一个元素可直接添加到结果中。
代码:
class Solution {
String res ="";
public String getPermutation(int n, int k) {
List<Integer> arr = new LinkedList<Integer>();
for(int i=0;i<n+1;i++){
arr.add(i+1);
}
k--;
for(int i = n; i >=1; i--){
int index = k/jiecheng(i-1);
res = res+arr.get(index);
arr.remove(index);
k-=index*jiecheng(i-1);
}
return res;
}
public int jiecheng(int n){
while(n>1){
return n*jiecheng(n-1);
}
return 1;
}
}