解leetcode题集....持续更新中

1.给定一个数组nums,写一个函数将数组中的所有0挪到数组末尾而且维持其他所有非零元素相对位置不变

举例:nums[3,7,0,6,0,3,2] 函数运行后结果为nums=[3,7,6,3,2,0,0]

public class Solution {
    public static void swap(int[] nums,int a,int b){
        int temp=nums[a];
        nums[a]=nums[b];
        nums[b]=temp;
    }
    public static void moveZeroes(int[] nums){
        int k=0;
        //nums中,[1....k)的元素均为非0元素
        //遍历到第i个元素后保证[0,....i]中的所有非0元素都按照顺序排列在[0,...k)中
        //同时[k,...i]都为0
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=0){  //nums[i]不为0
                swap(nums,k,i);
                k++;
            }
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int nums[]={4,5,0,7,0,6,9};
        moveZeroes(nums);
        for(int i=0;i<nums.length;i++){
            System.out.print(nums[i]+" ");
        }
    }
}

对撞指针

2.给定一个有序整型数组和一个整型数target,在其中寻找两个元素的和为target,返回这两个元素的索引。

可以定义两个索引 i,j,他们分别指向数组的开头和结尾,判断他们的和是否为target,是则返回,否则判断是比target小还是大,小则 i索引右移,因为数组是有序的,所以此时他们的和增大了,再次比较,若和比target大,则 j 左移,此时他们和减小了,再次和target比较,直到找到两个目标元素。code:

public class Solution {
    public static void twoSum(int[] nums,int target){
        int l=0;
        int r=nums.length-1;
        while(l<r){
            if((nums[l]+nums[r])==target){
                System.out.println("目标索引:"+l+" "+r);
                return;
            }else if((nums[l]+nums[r])<target){
                l++;
            }else{
                r--;
            }
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int nums[]={0,2,5,7,9,12,34,40,46};
        twoSum(nums,49);
    }
}

双索引技术(滑动窗口)

3.给定一个整型数组和数字s,找到数组中最短的一个连续子数组(即数组中的元素都是相邻的),使得连续子数组的数字和大于等于s,返回这个数组的长度

public class Solution {
    public static void swap(int[] nums,int a,int b){
        int temp=nums[a];
        nums[a]=nums[b];
        nums[b]=temp;
    }
    public static int minSubArrayLen(int[] nums,int target){
        int l=0,r=-1;//nums[l...r]为我们的滑动窗口
        int sum=0;  //子数组和
        int res=nums.length+1;  //返回的最短子数组长度
        while(l<nums.length){
            //r<nums.length-1是为了防止越界,后面有++r操作
            if(r<nums.length-1&&sum<target){
                sum+=nums[++r];
            }else{
                sum-=nums[l++];
            }
            //在滑动窗口右边界向右挪动后或左边界向右挪动后
            //都判断一次子数组和是否>=target
            if(sum>=target){
                res=Math.min(res,r-l+1);
            }
        }
        if(res==nums.length+1){
            return 0;
        }
        return res;
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int nums[]={0,2,5,9,1,0,2,10,4,1,1,11};
        System.out.println(minSubArrayLen(nums,15));
    }
}

4.在一个字符串中寻找没有重复字母的最长子串

如:”abcabcbb”,结果为”abc”
如:”bbbbbb”,结果为”b”
如:”pwwkew”,结果为”wke”
code:

public class Solution {
     public static byte charToByteAscii(char ch){  
            byte byteAscii = (byte)ch;  
            return byteAscii;  
     }  
    public static int lenOfLongestString(String s){
        int l=0,r=-1;     //滑动窗口为s[l.....r]
        int freq[]=new int[256];
        int res=0;   //最长没有重复字符的子字符串长度
        while(l<s.length()){
            if(r+1<s.length()&&freq[charToByteAscii(s.charAt(r+1))]==0){  //s.charAt(r+1)字符暂没重复
                freq[charToByteAscii(s.charAt(++r))]++;
            }else{
                freq[charToByteAscii(s.charAt(l++))]--;
            }
            res=Math.max(res, r-l+1);
        }
        return res;
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String s="sdfggbttryytn";
        System.out.println(lenOfLongestString(s));  
    }
}

5.给定一个字符串S和T,在S中寻找一个最短的子串,包含T中的所有字符

如:S=”ADOBECODEBANC”;T=”ABC”
结果为”BANC”
code:


public class Solution {
     public static boolean contain(String s,String t){  
           boolean flag=true;
           for(int i=0;i<t.length();i++){
               if(!s.contains(t.substring(i, i+1))){
                   flag=false;
               }   
           }
           return flag;
     }  
    public static int lenOfShortestString(String S,String T){
        int l=0,r=1;     //滑动窗口为s[l.....r]
        int res=S.length();   //最短包含目标字符串的子字符串长度
        while(l<S.length()){
            if(r<S.length()&&!contain(S.substring(l, r),T)){  //不包含
                r++;
            }else{          //包含
                l++;
            }
            if(contain(S.substring(l, r),T)){
                res=Math.min(res, r-l);
            }
        }
        return res;
    }
    public static void main(String[] args) {
        System.out.println(lenOfShortestString("ACBADINDAAB","ADB"));
    }
}

HashMap、HashSet在算法中的运用

6.给出一个整型数组nums,返回数组中的两个索引,使得nums[i]+nums[j]=target,两个索引不能相等

如:nums[5,1,3,5,8,7],target=8
返回[0,2] [2,3]
上面有一个相似的题目,但是上面那题的数组是有序的,通过对撞指针解决问题,而这题的数组没规定是有序的

public class Solution {
    public static void twoSum(int[] nums,int target){
        Map<Integer,Integer> record=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            int complement=target-nums[i];
            if(record.get(complement)!=null){
                System.out.println(i+" "+record.get(complement));
            }else{
                record.put(nums[i], i);
            }
        }
    }
    public static void main(String[] args) {
        int nums[]={3,5,6,6,6,233,5,6,89,1};
        twoSum(nums,11);
    }
}

7.给出一个整型数组和一个整数K,是否存在索引i和j,使得nums[i]==nums[j]且i和j的差不超过k

code:

public class Solution {
    public static boolean containsDuplicate(int[] nums,int k){
        Set<Integer> record=new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(record.contains(nums[i])){
                return true;
            }
            record.add(nums[i]);
            //保持record最多有k个
            if(record.size()==k+1){
                record.remove(nums[i-k]);
            }
        }
        return false;
    }
    public static void main(String[] args) {
        int nums[]={3,5,6,233,5,6,89,1};
        System.out.println(containsDuplicate(nums,3));
    }
}

链表算法

链表和数组都是一种顺序结构,但是使用数组我们可以随机访问数组中任一元素,只要给出索引就能以O(1)的时间复杂度找到那个元素。而链表不支持,我们只能从链表的头节点开始循着next指针依次向后寻找下一个元素

8.反转一个链表

code:


public class Solution {
    static class Node{
        int val;
        Node next;
        Node(int x){
            val=x;
            next=null;
        }
    }
    public static Node createLinkedList(int arr[],int n){
        if(n==0){
            return null;
        }
        Node head=new Node(arr[0]);
        Node curNode=head;
        for(int i=1;i<n;i++){
            curNode.next=new Node(arr[i]);
            curNode=curNode.next;
        }
        return head;
    }
    public static Node reverseList(Node head){
        Node pre=null;
        Node cur=head;
        while(cur!=null){
            Node next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;

    }
    public static void  printList(Node head){
        Node node=head;
        while(node!=null){
            System.out.print(node.val+"->");
            node=node.next;
        }
        System.out.print("NULL");
    }
    public static void main(String[] args) {
        int nums[]={3,4,7,2,9,6,1};
        printList(createLinkedList(nums,nums.length));
        System.out.println();
        printList(reverseList(createLinkedList(nums,nums.length)));
    }
}
//结果:
//3->4->7->2->9->6->1->NULL
//1->6->9->2->7->4->3->NULL

9.给出一个有序链表,删除其中所有重复元素,使得每个元素只保留一次

如:1->1->2,返回1->2
如:1->1->2->3->3,返回1->2->3
code:

public class Solution {
    .............
    public static Node removeDuplicateList(Node head){
        if(head==null){
            return null;
        }
        Node cur=head;
        Node nextUnequal=cur.next;
        while(nextUnequal!=null){
            if(cur.val==nextUnequal.val){
                nextUnequal=nextUnequal.next;
                if(nextUnequal==null){
                    cur.next=null;
                }
            }else{
                cur.next=nextUnequal;
                cur=nextUnequal;
            }
        }
        return head;
    }

    public static void  printList(Node head){
        Node node=head;
        while(node!=null){
            System.out.print(node.val+"->");
            node=node.next;
        }
        System.out.print("NULL");
    }
    public static void main(String[] args) {
        int nums[]={1,1,1,2,2,2,3,4,4};
        printList(createLinkedList(nums,nums.length));
        System.out.println();
        printList(removeDuplicateList(createLinkedList(nums,nums.length)));
    }
}
//结果:
//1->1->1->2->2->2->3->4->4->NULL
//1->2->3->4->NULL

10.给定一个链表,对于每两个相邻的节点,交换他们的位置

如:1->2->3->4->null
返回:2->1->4->3->null
只能对节点进行操作,不能直接修改节点的值
code:

public class Solution {
    ..............
    public static Node swapPairs(Node head){
        Node dummyNode=new Node(0);   //虚拟头节点
        dummyNode.next=head;
        Node p=dummyNode;
        while((p.next!=null)&&(p.next.next!=null)){
            Node node1=p.next;
            Node node2=node1.next;
            Node next=node2.next;

            node2.next=node1;
            node1.next=next;
            p.next=node2;

            p=node1;
        }
        return dummyNode.next;
    }
    ..............
    public static void main(String[] args) {
        int nums[]={1,2,3,4,5,6,7,8};
        printList(createLinkedList(nums,nums.length));
        System.out.println();
        printList(swapPairs(createLinkedList(nums,nums.length)));
    }
}
//1->2->3->4->5->6->7->8->NULL
//2->1->4->3->6->5->8->7->NULL

11.给定一个链表,每K个节点为一组,反转每一组的K个节点,K为正整数且小于等于链表长度。如果链表长度不是K的整数倍,则剩余部分不需要进行反转。

如:1->2->3->4->5->NULL
若K=2,则结果为:2->1->4->3->5->NULL
若K=3,结果为:3->2->1->4->5->NULL
若K=5,结果为:5->4->3->2->1->NULL
code:

public class Solution {
    .................
    public static boolean isNull(Node p,int k){
        for(int i=0;i<k;i++){
            p=p.next;
            if(p==null){
                return true;
            }
        }
        return false;
    }
    public static Node swapPairs(Node head,int k){
        Node dummyNode=new Node(0);   //虚拟头节点
        dummyNode.next=head;
        Node p=dummyNode;
        Node p1=p;
        Node[] node=new Node[k+1]; 
        while(!isNull(p,k)){
            for(int i=0;i<k+1;i++){
                node[i]=p1.next;
                p1=p1.next;
            }
            for(int i=0;i<k;i++){
                if(i==0){
                    node[i].next=node[k];
                }else{
                    node[i].next=node[i-1];
                }
            }
            p.next=node[k-1];
            p=node[0];
            p1=p;
        }

        return dummyNode.next;
    }
    .............
    public static void main(String[] args) {
        int nums[]={1,2,3,4,5,6,7};
        printList(createLinkedList(nums,nums.length));
        System.out.println();
        printList(swapPairs(createLinkedList(nums,nums.length),7));
    }
}
//1->2->3->4->5->6->7->NULL
//7->6->5->4->3->2->1->NULL

12.用O(nlogn)时间复杂度的算法为链表排序

当为链表进行排序时,由于不能随机的访问链表中的元素,那么大多数的O(nlogn)排序算法是不适用的,而归并排序在排序过程中是不需要索引在数组中来回跳动的,下面我抽出了对链表进行归并排序中的最重要的一部分展示:对两个排好序的链表进行合并,合并成一个有序的链表。剩下的就是不断递归合并,以实现最终的算法
code:

public class Solution {
    ................

    public static Node mergeList(Node head,Node l,Node r){
          Node dummyNode=new Node(0);   //虚拟头节点
          dummyNode.next=head;
          Node curNode=dummyNode;
          while(curNode.next!=null){
              if(l.val<=r.val){
                  curNode.next=l;
                  curNode= curNode.next;
                  l=l.next;
                  if(l==null){
                      curNode.next=r;
                      curNode=curNode.next;
                  }
              }else{  //l.val>r.val
                  curNode.next=r;
                  curNode= curNode.next;
                  r=r.next;
                  if(r==null){
                      curNode.next=l;
                      curNode=curNode.next;
                  }
              }
          }
          return dummyNode.next;
    }

    ...............
    public static void main(String[] args) {
        int nums[]={4,7,5,2,1,3,6};
        int num1[]={4,5,7};
        int num2[]={1,2,3,6};
        Node head=createLinkedList(nums,nums.length);
        printList(head);
        Node l=createLinkedList(num1,num1.length);
        Node r=createLinkedList(num2,num2.length);
        System.out.println();
        printList(l);
        System.out.println();
        printList(r);
        System.out.println();
        printList(mergeList(head,l,r));
    }
}
//4->7->5->2->1->3->6->NULL
//4->5->7->NULL
//1->2->3->6->NULL
//1->2->3->4->5->6->7->NULL

13.删除链表中某一节点

给出链表中某一待删除节点的索引,删除该节点

code:

public class Solution {
    ..................
    public static void delNode(Node node){
        if(node==null){
            return; 
        }
        if(node.next==null){
            node=null;
        }
         node.val=node.next.val;
         node.next=node.next.next;
    }
    ..................
    public static void main(String[] args) {
        int nums[]={4,7,5,2,1,3,6};
        Node head=createLinkedList(nums,nums.length);
        printList(head);
        Node curNode=head;
        while(curNode!=null){
            if(curNode.val==5){
                delNode(curNode);
                break;
            }
            curNode=curNode.next;
        }
        System.out.println();
        printList(head);
    }
}
//结果:
//删除前 :4->7->5->2->1->3->6->NULL
//删除后 :4->7->2->1->3->6->NULL

栈和队列

栈和递归算法的关系:常用自定义栈模拟系统栈,写出非递归程序(常见递归算法就是利用的系统栈)
栈顶元素反映了在嵌套的层次关系中,最近的需要匹配的元素

14.给出一个嵌套的整型列表。列表中的项或为一个整数,或为一个整型列表。设计一个迭代器,遍历这个整型列表中的所有整数。

-如[[1,1],2,[1,1]] ,遍历结果为 1,1,2,1,1
-如[1,[4,[6]]] ,遍历结果为1,4,6

code:
类NestInteger:

public class NestInteger {
    private int val;
    private boolean isInteger=false;
    private List<NestInteger> nestList;
    public NestInteger(int val) {   
        this.val = val;
        this.isInteger = true;
        this.nestList = null;
    }
    public NestInteger( List<NestInteger> nestList) {
        this.val = 0;
        this.isInteger = false;
        this.nestList = nestList;
    }
    public boolean isInteger(){
        return isInteger;
    }
    public int getInteger(){
        return val;
    }
    public List<NestInteger> getList(){
        return nestList;
    }
}

自定义迭代器:

public class NestIterator implements Iterable<NestInteger>,Iterator<NestInteger>{
    private  List<NestInteger> nestList =null;
    private List<NestInteger> nestList2 =new ArrayList<>();
    private int index=0;
    public NestIterator(List<NestInteger> nestList) {
        this.nestList = nestList;
    }
    @Override
    public boolean hasNext() {
        return index<nestList2.size();
    }
    @Override
    public NestInteger next() {
        return nestList2.get(index++);  
    }
    @Override
    public Iterator<NestInteger> iterator() {
        Stack s=new Stack<NestInteger>();
        for(int i=nestList.size()-1;i>=0;i--){
            s.push(nestList.get(i));
        }
        while(!s.isEmpty()){
            NestInteger nestInteger=(NestInteger) s.peek();
            s.pop();
            if(nestInteger.isInteger()){
                nestList2.add(nestInteger);
            }else{
                List<NestInteger> nests=nestInteger.getList();
                for(int j=nests.size()-1;j>=0;j--){
                    s.push(nests.get(j));
                }
            }
        }
        return this;
    }
}

测试类:

public class Solution {
    public static void main(String[] args) {    
        List<NestInteger> nests=Arrays.asList(new NestInteger(2),new NestInteger(3));
        List<NestInteger> nests2=Arrays.asList(new NestInteger(5));
        List<NestInteger> nests3=Arrays.asList(new NestInteger(1),new NestInteger(nests),new NestInteger(nests2));
        NestIterator iterator=new NestIterator(nests3);
        for(NestInteger in:iterator){
            System.out.print(in.getInteger()+" ");
        }
    }
}
//结果: 1  2  3  5

猜你喜欢

转载自blog.csdn.net/qq_33535433/article/details/79491942