leetcode字节跳动探索

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;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值