解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.给定一个数组nums和一个数值val,将数组中的所有等于val的元素删除,并返回剩余元素的个数
 public static int removeElement(int[] nums, int numsSize, int val){
        int count = 0;//计算与val值不等的元素
        int i = 0;
        while (i<numsSize  )//i和count初始相同  如果和val相等那么 i++
        //那么和val相同的值就在count位,直到下次第i位不等的值。替换第count位
        {
            if (nums[i] != val)
            {
                nums[count] = nums[i];//用和val不同的数把前面和val相同的覆盖
                count++;
            }
            i++;

        }
        System.out.println("移除后的元素:");
        for (int j = 0; j < count; j++)
        {
            System.out.println(nums[j]);
        }
        return count;
    }

    public static void main(String[] args) {
        int num[] = { 0, 1, 2, 2, 3, 0, 4, 2 };
        int a = 2;

        int b= removeElement(num, num.length, a);
        System.out.println("新的长度为:" +b);
    }
3.给定一个有序数组nums,对数组中的元素去重,使得原数组中的每个元素最多保留两个,返回去重后的数组长度
 public static int removeElement(int[] nums, int numsSize, int rs){
        int count = 0;
        int i = 0;
        int temp[]=new int[numsSize];
        while (i<numsSize  )
        //那么和val相同的值就在count位,直到下次第i位不等的值。替换第count位
        {
            if(temp[nums[i]]<rs){
                nums[count]=nums[i];
                count++;
                temp[nums[i]]++;

            }
            i++;

        }
        System.out.println("移除后的元素:");
        for (int j = 0; j < count; j++)
        {
            System.out.println(nums[j]);
        }
        return count;
    }

    public static void main(String[] args) {
        int num[] = { 1, 2, 2, 2 ,3, 3, 4 };
        int a = 2;

        int b= removeElement(num, num.length, a);
        System.out.println("新的长度为:" +b);
    }
4.给定一个有n个元素的数组,数组中的元素只有0,1,2三种可能,为这个数组排序
 public static void swap(int[] nums,int a,int b){
        int temp=nums[a];
        nums[a]=nums[b];
        nums[b]=temp;
    }
    //时间复杂度:O(n)
    //空间复杂度:O(1)  三路快排思想
    public static void sortedColors(int[] nums){
        int zero=-1;  //nums[0....zero]==0
        int two=nums.length;  //nums[two..n-1]==2
        for(int i=0;i<two;){
            if(nums[i]==1){
                i++;
            }else if(nums[i]==2){
                swap(nums,i,--two);
            }else{
                assert(nums[i]==0);  //nums[i]==0必须等于0
                swap(nums,++zero,i++);
            }
        }
    }

    public static void main(String[] args) {
        int num[] = { 2,1,1,0,2,1,1,0,1,2};
        sortedColors(num);
        for (int i : num) {
            System.out.println(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
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值