LeetCode简单题

本文详细介绍了LeetCode上的一些简单题目,包括回文数判断、数组元素移除、有效括号检查、用栈实现队列等。文章通过反证法、双指针、栈等数据结构和算法进行问题分析,并给出了相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此篇文章用户记录leetcode的简单题

leetcode9给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

分析 看到这道题目首先我想的是反证法比如121是不是一个回文数只需要把他反过来121看两数是否需要相等即可,但是发现编译报错,这是因为int类型可能会爆表,比如x = 2,147,483,646 也就是反过来一定会超出范围所以不可行,我们只需要比较一半就可以定义一个revertedNumber 当x > renvertedNumber去做比较即可 代码如下

	class Solution {
	    public boolean isPalindrome(int x) {
	        if(x < 0 || (x % 10 == 0 && x != 0)){
	            return false;
	        }
	        int revertedNumber = 0;
	        while(x > revertedNumber){
	            revertedNumber = revertedNumber * 10 + x % 10;
	            x /= 10;
	        } 
	        return x == revertedNumber || x == revertedNumber / 10;
	    }
}

LeetCode27:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

分析 双指针法: 一个指针指向有效元素个数 另一个指针用来判断是不是要移除的数字,如果不是要移除的数字那么就把他给有效数字的指针即可,然后有效指针自增。代码如下

 public int removeElement(int[] nums, int val) {
		if (nums == null || nums.length == 0)
			return 0;
		int j = 0;
		for (int i = 0; i < nums.length; i++) {
			if (nums[i] != val) {
				nums[j] = nums[i];
				j++;
			}
		}
		return j;
	}

双指针优化 如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4][5,2,3,4],同样满足题目要求。这个优化在序列中 元素的数量较少时非常有效。此方法借鉴了leetcode官方。

class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length;
        while (left < right) {
            if (nums[left] == val) {
                nums[left] = nums[right - 1];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }
}

如果换成int right = nums.length - 1
后面if换成nums[left] = nums[right] 会正确吗?
注意题目返回的是新的长度 所以这样一定不可以


leetcode20
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

分析 用(){}[]<>的ASCII值差为1或者为2所以只需要用一个栈来存储括号,每次进来看栈顶的top-c==-1||-2(由于左括号必须以正确的顺序闭合。)就可以了代码如下

![在这里插入图片描述](https://img-blog.csdnimg.cn/202105251910463.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hhb2hhbzE5MDIwMjAyMzg=,size_16,color_FFFFFF,t_70)class Solution {
    public boolean isValid(String s) {
        if(s.length() % 2 == 1){
            return false;
        }
        Stack<Character>stack = new Stack<Character>();
        char c;
        boolean a = true;
        for(int i = 0; i < s.length(); i++){
            c = s.charAt(i);
            if(stack.empty()){
                stack.push(c);
            }else{
                char top = stack.peek();
                if(top -c == -1 || top - c == -2){
                    stack.pop();
                }else{
                    stack.push(c);
                }
            }
        }
        return a == stack.isEmpty();
    }
}

leetcode232
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
 

说明:

你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
 

进阶:

你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。

来源:力扣(LeetCode)

分析:用栈实现队列就需要一个辅助栈进队的话直接进 出队先把A的元素全移到B然后弹出B栈顶的元素即可

在这里插入图片描述

初始 两个栈 进队列1-6
在这里插入图片描述
出栈
代码如下
class MyQueue {
private Stack a;// 输入栈
private Stack b;// 输出栈

    public MyQueue() {
        a = new Stack<>();
        b = new Stack<>();
    }
    
    public void push(int x) {
        a.push(x);
    }
    
    public int pop() {
        // 如果b栈为空,则将a栈全部弹出并压入b栈中,然后b.pop()
        if(b.empty()){
            while(!a.empty()){
                b.push(a.pop());
            }
        }
        return b.pop();
    }
    
    public int peek() {
        if(b.empty()){
            while(!a.empty()){
                b.push(a.pop());
            }
        }
        return b.peek();
    }
    
    public boolean empty() {
        return a.empty() && b.empty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

leetode167两数之和
给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

方法一:双指针法
在这里插入图片描述
定义一个指针low等于0,一个指针high等于numbers.length-1
然后low与high对应的值相加如果小,则low++;
如果大则high–;

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int low = 0;
        int high = numbers.length - 1;
        while(low < high){
            int sum = numbers[low] + numbers[high];
            if(sum < target){
                low++;
            }else if(sum > target){
                high--;
            }else{
                return new int[]{low + 1, high + 1};
            }
        }
        return null;
    }
}

方法二 二分查找法
在这里插入图片描述
定义两个指针low每次等于i+1 high等于numbers.length - 1
每次用target- nums[i]看这个值是否存在low-high的区间中
用二分法
如果小于中间值则high = mid - 1
如果大于中间值则low = mid + 1

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        for(int i = 0; i < numbers.length; i++){
            int low = i + 1;
            int high = numbers.length - 1;
            if(target - numbers[i] > numbers[high]){
                continue;
            }
            if(target - numbers[i] < numbers[low]){
                break;
            }
            while(low <= high){
                int mid = (high + low)/2 + low;
                if(numbers[mid] == target - numbers[i]){
                    return new int[]{low + 1, high + 1};
                }else if (numbers[mid] > target - numbers[i]){
                    high = mid - 1;
                }else{
                    low = mid + 1;
                }
            }
        }
        return new int[]{-1,-1};
    }
}

leetcode905按奇偶排序数组
给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后
跟着所有奇数元素你可以返回满足此条件的任何数组作为答案。

方法一:选择排序法
运用选择排序的方法遍历所有数字 遇到奇数和后面的偶数换位置

class Solution {
    public int[] sortArrayByParity(int[] nums) {
        for(int i = 0; i < nums.length; i++){
            if(nums[i] % 2 == 1){
                for(int j = i + 1; j < nums.length; j++){
                    if(nums[j] % 2 == 0){
                        int temp = nums[i];
                        nums[i] = nums[j];
                        nums[j] = temp;
                    }
                }
            }
        }
        return nums;
    }
}

方法二:双指针法
两个指针一前一后 看两遍是奇数还是偶数
在这里插入图片描述

代码如下

class Solution {
    public int[] sortArrayByParity(int[] nums) {
        int l = 0;
        int r = nums.length - 1;
        while(l < r){
            if(nums[l] % 2 == 0 && nums[r] % 2 == 0){
                l++;
            }else if(nums[l] % 2 == 1 && nums[r] % 2 == 0){
                int temp = nums[l];
                nums[l] = nums[r];
                nums[r] = temp;
            }else if(nums[l] % 2 == 1 && nums[r] % 2 == 1){
                r--;
            }else{
                l++;
                r--;
            }
        }
        return nums;
    }
}

leetcode66
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

方法:倒序遍历
我们需要考虑这几种情况
在这里插入图片描述

每次的数字加1之后应该%10 然后carry为每次的数字/10

class Solution {
    public int[] plusOne(int[] digits) {
        int carry = 1;
        for(int i = digits.length - 1; i >= 0; i--){
            int num = digits[i] + carry;
            digits[i] = num % 10;
            carry = num / 10;
            if(carry == 0){
                break;
            }
        }
        if(carry == 1){
            int[] arr = new int[digits.length + 1];
            arr[0] = 1;
            return arr;
        }
        return digits;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值