快手1面-复原IP

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路分析

采用剪枝的思想进行解答;
(1)字符串的长度小于 4 或者大于 12 ,一定不能拼凑出合法的 ip 地址,退出;
(2)每一个结点可以选择截取的方法只有 3 种:截 1 位、截 2 位、截 3 位,因此每一个结点可以生长出的分支最多只有 3 条分支;

代码实现

// import java.util.ArrayDeque;
// import java.util.ArrayList;
// import java.util.Deque;
// import java.util.List;
// import java.util.Stack;

public class Solution {
    // splitTimes:已经分割出多少个 ip 段;
    // begin:截取 ip 段的起始位置;
    // path:记录从根结点到叶子结点的一个路径(回溯算法常规变量,是一个栈);
    // res:记录结果集的变量,常规变量

    public List<String> restoreIpAddresses(String s) {
        int len = s.length();
        List<String> res = new ArrayList<>();
        // 如果长度不够,不搜索
        if (len < 4 || len > 12) {
            return res;
        }

        Deque<String> path = new ArrayDeque<>(4);
        int splitTimes = 0;
        dfs(s, len, splitTimes, 0, path, res);
        return res;
    }

    /**
     * 判断 s 的子区间 [left, right] 是否能够成为一个 ip 段
     * 判断的同时顺便把类型转了
     *
     * @param s
     * @param left
     * @param right
     * @return
     */
    private int judgeIfIpSegment(String s, int left, int right) {
        int len = right - left + 1;

        // 大于 1 位的时候,不能以 0 开头
        if (len > 1 && s.charAt(left) == '0') {
            return -1;
        }

        // 转成 int 类型
        int res = 0;
        for (int i = left; i <= right; i++) {
            res = res * 10 + s.charAt(i) - '0';
        }

        if (res > 255) {
            return -1;
        }
        return res;
    }

    private void dfs(String s, int len, int split, int begin, Deque<String> path, List<String> res) {
        if (begin == len) {
            if (split == 4) {
                res.add(String.join(".", path));
            }
            return;
        }

        // 看到剩下的不够了,就退出(剪枝),len - begin 表示剩余的还未分割的字符串的位数
        if (len - begin < (4 - split) || len - begin > 3 * (4 - split)) {
            return;
        }

        for (int i = 0; i < 3; i++) {
            if (begin + i >= len) {
                break;
            }

            int ipSegment = judgeIfIpSegment(s, begin, begin + i);
            if (ipSegment != -1) {
                // 在判断是 ip 段的情况下,才去做截取
                path.addLast(ipSegment + "");
                dfs(s, len, split + 1, begin + i + 1, path, res);
                path.removeLast();
            }
        }
    }
}
### 快手 AES-128-CBC 加密实现 在快手平台的消息推送和其他接口交互中,AES-128-CBC 是一种常用的加密方式。这种模式下,每个明文块都与前一个密文块进行异或操作后再被加密,这增加了安全性并防止相同明文产生相同的密文。 对于 AES-128-CBC 来说,密钥长度固定为 16 字节 (128 bit)[^1]。为了确保数据的安全性和一致性,在实际开发过程中需要注意初始化向量(IV)的选择;通常 IV 应该是一个随机值,并且每次加密时都应该改变它以增加系统的不可预测性。 下给出 Python 中基于 PyCryptodome 库的一个简单例子来展示如何使用 AES-128-CBC 进行加密: ```python from Crypto.Cipher import AES import base64 def pad(text): """填充函数""" while len(text) % 16 != 0: text += b'\0' return text key = 'thisisaverysecret'.encode('utf-8')[:16] # 密钥应为16字节长 iv = 'aninitializationve'.encode('utf-8') # 初始化向量同样需要16字节 cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = "Hello world!" padded_plaintext = pad(plaintext.encode()) ciphertext = cipher.encrypt(padded_plaintext) print(base64.b64encode(ciphertext).decode()) # 输出Base64编码后的密文 ``` 解密过程则相反,先通过 Base64 解码获取到原始的 ciphertext,再利用同样的 key 和 iv 创建一个新的 Cipher 对象来进行解密操作: ```python decrypted_padded_text = cipher.decrypt(ciphertext) original_message = decrypted_padded_text.rstrip(b'\0').decode() print(original_message) # 打印恢复出来的原文 ``` 当涉及到具体的应用场景比如处理来自快手平台的消息推送时,则需按照官方文档的要求设置相应的参数[^3]。例如配置正确的 app_secret 或者其他必要的认证信息用于构建有效的请求头等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值