leetcode 383. Ransom Note(思路,++i i++的区别,String)

本文探讨了如何判断一个字符串是否能由另一个字符串中的字符组成,重点介绍了LeetCode上的一道经典题目及其解决方案。通过计算两个字符串中各字符的频率,确保前者的每个字符数量不超过后者,从而验证前者的字符串是否能完全由后者的字符构成。

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

Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.

Each letter in the magazine string can only be used once in your ransom note.

Note:
You may assume that both strings contain only lowercase letters.

canConstruct(“a”, “b”) -> false
canConstruct(“aa”, “ab”) -> false
canConstruct(“aa”, “aab”) -> true

题意:

前面的字符串里的字母是否被后面字符串的字母包含(注意不需要位置连续)

思路:

采用leetcode热门解法,计算两字符串里26种字母的个数,前面每种字母应小于等于后面

知识点:
1. i++和++i的区别

**总结:

  1. i都要+1
  2. j=i++,先执行j=i,然后i+1,所以j=0;
  3. j=++i,先执行i+1,然后j=i,所以j=1**

原文:http://hinylover.space/2017/07/30/java-i-self-increament/ 从底层解释,非常详细。
截取如下:

int i = 0;
int j1 = i++; // 正确
int j2 = ++i; // 正确
i++; // 正确
++i; // 正确
i++ = 5; // 编译不通过
++i = 5; // 编译不通过
{
    int i = 1;
    int j1 = i++;
    System.out.println("j1=" + j1); // 输出 j1=1
    System.out.println("i=" + i); // 输出 i=2
}
{
    int i = 1;
    int j2 = ++i;
    System.out.println("j2=" + j2); // 输出 j2=2
    System.out.println("i=" + i); // 输出 i=2
}

无论是i++和++i指令,对于i变量本身来说是没有任何区别,指令执行的结果都是i变量的值加1。而对于j1和j2来说,这就是区别所在。

实现原理

++i和i++实现源码如下:

public class Test {
    public void testIPlus() {
        int i = 0;
        int j = i++; //i=1,j=0
    }
    public void testPlusI() {
        int i = 0;
        int j = ++i; //i=1,j=1
    }
}

将上面的源代码编译之后,使用javap命令查看编译生成的代码(忽略次要代码)如下:

public void testIPlus();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=1
         0: iconst_0               // 生成整数0
         1: istore_1               // 将整数0赋值给1号存储单元(即变量i)
         2: iload_1                // 将1号存储单元的值加载到数据栈(此时 i=0,栈顶值为0)
         3: iinc          1, 1     // 1号存储单元的值+1(此时 i=1)
         6: istore_2               // 将数据栈顶的值(0)取出来赋值给2号存储单元(即变量j,此时i=1,j=0)
         7: return                 // 返回时:i=1,j=0
      LineNumberTable:
        line 4: 0
        line 5: 2
        line 6: 7
  public void testPlusI();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=1
         0: iconst_0                // 生成整数0
         1: istore_1                // 将整数0赋值给1号存储单元(即变量i)
         2: iinc          1, 1      // 1号存储单元的值+1(此时 i=1)
         5: iload_1                 // 将1号存储单元的值加载到数据栈(此时 i=1,栈顶值为1)
         6: istore_2                // 将数据栈顶的值(1)取出来赋值给2号存储单元(即变量j,此时i=1,j=1)
         7: return                  // 返回时:i=1,j=1
      LineNumberTable:
        line 9: 0
        line 10: 2
        line 11: 7
2. String
  1. String类的length()方法有()
  2. charAt()方法是字符串的某的位置上的字符转换成char格式,`str.charAt(i)
3. ASC2码的运用

char格式 - char格式 = ASC2码的差值
例如:
int k = 'A'-'a' / /k = 97-65=32;

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] num = new int[26];
        for(int i=0;i<magazine.length();i++){
            num[magazine.charAt(i)-'a']++;
        }
        for(int i=0;i<ransomNote.length();i++){
            num[ransomNote.charAt(i)-'a']--;
            //这里由于没有赋值给一个变量,下面的if条件里直接使用,所以可以用x--;
            //如果要赋值变量,就要用 int k = --x;
            //不能用int k = x--;
            if(num[ransomNote.charAt(i)-'a']<0){
                return false;
            }
        }
        return true;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值