LeetCode-Easy-2-5

文章目录

    • 题目20 有效括号
      • 代码
      • 暴力求解
        • 思路:
      • 代码
    • 题目21 合并两个有序链表
      • 迭代解法
      • 递归解法
    • 题目26 删除排序数组中的重复项
      • 代码
    • 题目27 移除元素
      • 说明:
      • 提示
      • 方法:双指针 —— 当要删除的元素很少时
      • 代码
    • 题目28 实现strStr()
      • 说明:
      • 方法:子串逐一比较 - 线性时间复杂度
      • 代码

题目20 有效括号

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

注意空字符串可被认为是有效字符串。

示例 1:
输入: “()”
输出: true

示例 2:
输入: “()[]{}”
输出: true

示例 3:
输入: “(]”
输出: false

示例 4:
输入: “([)]”
输出: false

示例 5:
输入: “{[]}”
输出: true

使用后进先出的栈判断
如果字符是左括号,将左括号压入栈
如果字符是右括号,判断栈顶对象与该字符是否一样,一样则是有效的,不一样就是无效的
遍历字符串中的字符即可

代码

class Solution {
    public boolean isValid(String s) {
        // 为空默认返回true
        if (s == null ) return true;
        // 栈是Vector的一个子类,它实现了一个标准的后进先出的栈。
        Stack<Character> stack = new Stack<>();
        int len = s.length();// 字符串中有多少字符
        for ( int i = 0 ; i < len ; i++ ) {
            // 当前字符
            char cur = s.charAt(i);
            if (cur == '(' ||cur == '{' ||cur == '[' ) {
                // Object push(Object element) 把项压入堆栈顶部。
                stack.push(cur);
            }else{
                // 开头不是左括号
                if(stack.isEmpty())return false;
                // 	Object pop( ) 移除堆栈顶部的对象,并作为此函数的值返回该对象。
                char pop = stack.pop();
                // pop是左括号 cur是右括号 判断
                if(pop == '(' && cur ==')' || pop == '{' && cur =='}'||pop == '[' && cur ==']'){
                    continue;
                }else{
                    // 不是有效括号
                    return false;
                }
            }
        }
        // 遍历结束后 stack为空说明是有效括号
        return stack.isEmpty()?true:false;
    }
}

暴力求解

字符串中有效的括号有两种:

  • 嵌套的如:
    { ( [ { } ] ) }
  • 并排的如:
    ( ) { } [ ] ( )
  • 还有两种复合的:
    { ( ) } [ ( { } ) ]

思路:

  1. 首先括号成对出现,奇数的一定不符合。
  2. 然后每次消去一个最小的完整括号,如果全部消除,说明是有效括号,如果replace之后字符串不发生变化且长度不为0,说明不是有效括号。

代码

class Solution {
    public boolean isValid(String s) {
        String s1 = s;
        if (s.length() % 2 != 0) {
            return false;
        }
        while (s.length() != 0) {
            s = s.replace("{}", "");
            s = s.replace("()", "");
            s = s.replace("[]", "");
            if (s == s1) {
                return false;
            }
            s1 = s;
        }
        return true;
    }
}

题目21 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

因为链表是升序的,我们只需要遍历每个链表的头,比较一下哪个小就把哪个链表的头拿出来放到新的链表中,一直这样循环,直到有一个链表为空,然后我们再把另一个不为空的链表挂到新的链表中。

// 链表
public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

迭代解法

    public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
        //下面4行是空判断
        if (linked1 == null)
            return linked2;
        if (linked2 == null)
            return linked1;
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        while (linked1 != null && linked2 != null) {
            //比较一下,哪个小就把哪个放到新的链表中
            if (linked1.val <= linked2.val) {
                curr.next = linked1;
                linked1 = linked1.next;
            } else {
                curr.next = linked2;
                linked2 = linked2.next;
            }
            curr = curr.next;
        }
        //然后把那个不为空的链表挂到新的链表中
        curr.next = linked1 == null ? linked2 : linked1;
        return dummy.next;
    }

递归解法

    public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
        if (linked1 == null)
            return linked2;
        if (linked2 == null)
            return linked1;
        if (linked1.val < linked2.val) {
            linked1.next = mergeTwoLists(linked1.next, linked2);
            return linked1;
        } else {
            linked2.next = mergeTwoLists(linked1, linked2.next);
            return linked2;
        }
    }

题目26 删除排序数组中的重复项

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。

示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素。

说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝

在函数里修改输入数组对于调用者是可见的。
根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。

int len = removeDuplicates(nums);

在函数里修改输入数组对于调用者是可见的。
根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。

for (int i = 0; i < len; i++) {
    print(nums[i]);
}

代码

class Solution {
    public int removeDuplicates(int[] nums) {
        // 入参非空判断
        if(nums == null)  return 0;
        // 慢指针
        int result = 0;
        // nums = [1,1,2]
        for (int i = 0;/*快指针*/ i < nums.length; i++) {
            // 快慢指针不同,对应的值不同
            if (nums[result] != nums[i] && result != i) {
                result ++;// 符合条件的数据指针
                nums[result] = nums[i]; // 不重复数据组装赋值
            }
        }
        // 指针需要加一表示长度。根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
        return result+1;
    }
}

题目27 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。
示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝

int len = removeDuplicates(nums);

在函数里修改输入数组对于调用者是可见的。
根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。

for (int i = 0; i < len; i++) {
    print(nums[i]);
}

提示

  1. 尝试双指针法。
  2. 你是否使用“元素顺序可以更改”这一属性?
  3. 当要删除的元素很少时会发生什么?

方法:双指针 —— 当要删除的元素很少时

思路

现在考虑数组包含很少的要删除的元素的情况。例如,num=[1,2,3,5,4],Val=4。之前的算法会对前四个元素做不必要的复制操作。另一个例子是 num=[4,1,2,3,5],Val=4。似乎没有必要将 [1,2,3,5] 这几个元素左移一步,因为问题描述中提到元素的顺序可以更改。

算法

当我们遇到 nums[i] = val 时,我们可以将当前元素与最后一个元素进行交换,并释放最后一个元素。这实际上使数组的大小减少了 1。

请注意,被交换的最后一个元素可能是您想要移除的值。但是不要担心,在下一次迭代中,我们仍然会检查这个元素。

代码

public int removeElement(int[] nums, int val) {
    int i = 0;
    int n = nums.length;
    while (i < n) {
        if (nums[i] == val) {
            nums[i] = nums[n - 1];
            // reduce array size by one
            n--;
        } else {
            i++;
        }
    }
    return n;
}

题目28 实现strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = “hello”, needle = “ll”
输出: 2

示例 2:

输入: haystack = “aaaaa”, needle = “bba”
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

方法:子串逐一比较 - 线性时间复杂度

最直接的方法 - 沿着字符换逐步移动滑动窗口,将窗口内的子串与 needle 字符串比较。

LeetCode-Easy-2-5_第1张图片

代码

class Solution {
  public int strStr(String haystack, String needle) {
    int L = needle.length(), n = haystack.length();

    for (int start = 0; start < n - L + 1; ++start) {
      if (haystack.substring(start, start + L).equals(needle)) {
        return start;
      }
    }
    return -1;
  }
}

你可能感兴趣的:(LeetCode)