算法通过村--第五关白银挑战

一、用栈实现队列

用两个栈stack1(用于实现入队操作的栈)和stack2(用于实现出队操作的栈)。要实现队列的先进先出,在出队的时候先检查stack2是否为空,将需要出栈的stack1的内容全部压栈到stack2中,然后从stack2实现出队操作。总的来说就是经过stack2“颠倒了一下”。

class MyQueue {
        Stack<Integer> stack1;
        Stack<Integer> stack2;
    public MyQueue() {
        stack1=new Stack<Integer>();
        stack2=new Stack<Integer>();
    }
    
    public void push(int x) {
        this.stack1.push(x);
    }
    
    public int pop() {
        if(this.stack2.empty()){
            while(!this.stack1.empty())
                this.stack2.push((Integer)this.stack1.pop());
        }
        return this.stack2.pop();
    }
    
    public int peek() {
        if(this.stack2.empty()){
            while(!this.stack1.empty())
                this.stack2.push((Integer)this.stack1.pop());
        }
        return this.stack2.peek();
    }
    
    public boolean empty() {
        return stack1.empty()&&stack2.empty();
    }
}

二、用队列实现栈

这个需要在压栈的时候设计一下。需要实现栈的后进先出,入栈的时候就得让后面进的排队排到队列的前面。需要借助两个队列queue1和queue2。入队时先将入队元素放到queue2中,再将queue1中的所有元素出队到queue2中,此时在queue2中,后进来的元素就拍到了队首,queue1为空,再将queue2的元素全部出队到queue1中。出栈的时候从queue1中出栈即可。

class MyStack {
        Queue<Integer> queue1;
        Queue<Integer> queue2;
    public MyStack() {
        queue1= new LinkedList<Integer>();
        queue2= new LinkedList<Integer>();        
    }
    
    public void push(int x) {
        queue2.offer(x);
        while(!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        while(!queue2.isEmpty()){
            queue1.offer(queue2.poll());
        }
    }
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty();
    }
}

三、两数之和

 

 借助hash将本来for循环中的查询target-nums[i]这个值是否存在于数组中的时间给优化掉了。所以时间复杂度为O(n)

    public int[] twoSum(int[] nums, int target) {
        int[] ans=new int[]{-1,-1};
        int len=nums.length;
        HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();

        for(int i=0;i<len;i++){
            map.put(nums[i],i);
        }
        for(int i=0;i<len;i++){
            int value=target-nums[i];
            if(map.containsKey(value)&&map.get(value)!=i){
                ans[0]=i;
                ans[1]=map.get(value);
            }
        }
        return ans;
    }

四、三数之和

因为要求 答案中不可以包含重复的三元组。所以用哈希会比较麻烦,如果用暴力枚举会是O(n^3)的时间复杂度。为了答案中不可以包含重复的三元组,可以先将数组排序,排序后,先第一个枚举for循环中如果上一个值和当前值相等,则跳过此轮枚举。枚举nums[i],接下来就变成了target=0-nums[i]的“两数之和”问题了。

    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int len=nums.length;
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        for(int i=0;i<len;i++){
            if(i>0&&nums[i]==nums[i-1])
                continue;
            int target=0-nums[i];
            int left=i+1;
            int right=len-1;
            while(left<right){
                if(nums[left]+nums[right]>target)
                    right--;
                else if(nums[left]+nums[right]<target)
                    left++;
                else if(i!=left&&i!=right&&left!=right){
                    List<Integer> temp=new ArrayList<Integer>();
                    temp.add(nums[i]);
                    temp.add(nums[left]);
                    temp.add(nums[right]);
                    ans.add(temp);
                    left++;
                    right--;
                    while(left<len&&nums[left]==nums[left-1])
                        left++;
                    while(right>=0&&nums[right]==nums[right+1])
                        right--;
                }
                else
                    left=right;
            }
        }
        return ans;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值