普通视图

发现新文章,点击刷新页面。
今天 — 2025年1月18日技术

不花一分钱,快速打造专属个性化个人主页

作者 吾心飞享
2025年1月18日 11:26
引言 个人博客的价值与重要性 在当今数字化信息爆炸的时代,个人博客不仅是一个表达自我、分享知识和见解的平台,更是建立个人品牌、提升在线影响力的重要工具。对于技术专家、内容创作者以及任何希望在网络空间中

Outlaw挖矿僵尸网络近期活动分析

2025年1月14日 18:00

1          概述

近期,安天CERT监测到多起Outlaw挖矿僵尸网络攻击事件,该挖矿僵尸网络最早于2018年被发现,主要针对云服务器从事挖矿活动,持续活跃。安天CERT在分析近期的攻击事件中发现,该挖矿僵尸网络样本在第三版本基础上有了重要更新,其功能更加多样、隐匿性更高、清除更加困难。主要传播途径和功能依旧是SSH暴力破解攻击目标系统,植入SS

求出数组中最大序列值

2025年1月3日 09:21

方法一:动态规划

思路

长度为 $2k$ 的序列的值的计算方式为,先将其拆成长度相同的前后子串,然后分别计算各子串的所有元素的按位或的结果,再将两个按位或的结果进行按位异或。为了求出 $\textit{nums}$ 的长度为 $2k$ 的子序列的最大值,可以将 $\textit{nums}$ 分成左右两半,分别求出每一半中,长度为 $k$ 的子序列的按位或的所有可能性,再两两求异或的最大值。这样的分法一共有 $n-2k+1$ 种,其中 $n$ 为数组 $\textit{nums}$ 的长度。并且我们可以用动态规划的方法来求出长度为 $k$ 的子序列的按位或的结果的所有可能性。

记 $\textit{dp}[i][j]$ 为哈希集合,表示 $\textit{nums}[0...i]$ 中长度为 $j$ 的自序列按位或的所有可能性。$j \leq k$,且当 $j$ 为 $0$ 时,$\textit{dp}[i][j]$ 为空集。又根据题目限制,$\textit{nums}$ 元素的值为 $0$ 到 $127$,因此 $\textit{dp}[i][j]$ 最多包含 $128$ 个元素。进行转移时,$\textit{dp}[i][j]$ 首先会包含 $\textit{dp}[i-1][j]$ 的所有元素,表示不选取 $\textit{nums}[i]$。还可以将 $\textit{dp}[i-1][j-1]$ 中的所有元素与 $\textit{nums}[i]$ 进行按位或,将结果添加进 $\textit{dp}[i][j]$,表示选取$\textit{nums}[i]$。我们可以将上述步骤抽象成一个函数,并进一步降低空间复杂度,只返回值 $j=k$ 时的 $dp$值,可以算出左一半的长度为 $k$ 的子序列的按位或的所有可能性。再将 $\textit{nums}$ 进行逆序后再次应用这个函数,即可计算出右一半的的长度为 $k$ 的子序列的按位或的所有可能性。再两两求异或的最大值返回。

我们可以将

代码

###Python

class Solution:
    def maxValue(self, nums: List[int], k: int) -> int:
        def findORs(nums: List[int], k: int) -> List[set[int]]:
            dp = []
            prev = [set() for _ in range(k + 1)]
            prev[0].add(0) 
            for i, num in enumerate(nums):
                for j in range(min(k - 1, i + 1), -1, -1):
                    for x in prev[j]:
                        prev[j + 1].add(x | num)
                dp.append(prev[k].copy())
            return dp

        A = findORs(nums, k)
        B = findORs(nums[::-1], k)

        mx = 0
        for i in range(k - 1, len(nums) - k):
                mx = max(mx, *(a ^ b for a in A[i] for b in B[-i - 2]))
        return mx

###Java

class Solution {
    public int maxValue(int[] nums, int k) {
        List<Set<Integer>> A = findORs(nums, k);
        List<Set<Integer>> B = findORs(reverse(nums), k);
        int mx = 0;
        for (int i = k - 1; i < nums.length - k; i++) {
            for (int a : A.get(i)) {
                for (int b : B.get(nums.length - i - 2)) {
                    mx = Math.max(mx, a ^ b);
                }
            }
        }
        return mx;
    }

    private List<Set<Integer>> findORs(int[] nums, int k) {
        List<Set<Integer>> dp = new ArrayList<>();
        List<Set<Integer>> prev = new ArrayList<>();
        for (int i = 0; i <= k; i++) {
            prev.add(new HashSet<>());
        }
        prev.get(0).add(0);
        for (int i = 0; i < nums.length; i++) {
            for (int j = Math.min(k - 1, i + 1); j >= 0; j--) {
                for (int x : prev.get(j)) {
                    prev.get(j + 1).add(x | nums[i]);
                }
            }
            dp.add(new HashSet<>(prev.get(k)));
        }
        return dp;
    }

    private int[] reverse(int[] nums) {
        int[] reversed = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            reversed[i] = nums[nums.length - 1 - i];
        }
        return reversed;
    }
}

###C#

public class Solution {
    public int MaxValue(int[] nums, int k) {
        var A = FindORs(nums, k);
        Array.Reverse(nums);
        var B = FindORs(nums, k);
        int mx = 0;
        for (int i = k - 1; i < nums.Length - k; i++) {
            foreach (int a in A[i]) {
                foreach (int b in B[nums.Length - i - 2]) {
                    mx = Math.Max(mx, a ^ b);
                }
            }
        }
        return mx;
    }

    public List<HashSet<int>> FindORs(int[] nums, int k) {
        var dp = new List<HashSet<int>>();
        var prev = new List<HashSet<int>>();
        for (int i = 0; i <= k; i++) {
            prev.Add(new HashSet<int>());
        }
        prev[0].Add(0);
        for (int i = 0; i < nums.Length; i++) {
            for (int j = Math.Min(k - 1, i + 1); j >= 0; j--) {
                foreach (int x in prev[j]) {
                    prev[j + 1].Add(x | nums[i]);
                }
            }
            dp.Add(new HashSet<int>(prev[k]));
        }
        return dp;
    }
}

###C++

class Solution {
public:
    int maxValue(vector<int>& nums, int k) {
        auto findORs = [&](const vector<int>& nums, int k) -> vector<unordered_set<int>> {
            vector<unordered_set<int>> dp;
            vector<unordered_set<int>> prev(k + 1);
            prev[0].insert(0);
            for (int i = 0; i < nums.size(); ++i) {
                for (int j = min(k - 1, i + 1); j >= 0; --j) {
                    for (int x : prev[j]) {
                        prev[j + 1].insert(x | nums[i]);
                    }
                }
                dp.push_back(prev[k]);
            }
            return dp;
        };

        vector<unordered_set<int>> A = findORs(nums, k);
        vector<unordered_set<int>> B = findORs(vector<int>(nums.rbegin(), nums.rend()), k);
        int mx = 0;
        for (size_t i = k - 1; i < nums.size() - k; ++i) {
            for (int a : A[i]) {
                for (int b : B[nums.size() - i - 2]) {
                    mx = max(mx, a ^ b);
                }
            }
        }
        return mx;
    }
};

###Go

func maxValue(nums []int, k int) int {
    findORs := func(nums []int, k int) []map[int]bool {
dp := make([]map[int]bool, 0)
prev := make([]map[int]bool, k + 1)
for i := 0; i <= k; i++ {
prev[i] = make(map[int]bool)
}
prev[0][0] = true

for i := 0; i < len(nums); i++ {
for j := min(k - 1, i + 1); j >= 0; j-- {
for x := range prev[j] {
prev[j + 1][x | nums[i]] = true
}
}
current := make(map[int]bool)
for key := range prev[k] {
current[key] = true
}
dp = append(dp, current)
}
return dp
}

A := findORs(nums, k)
reverse(nums)
B := findORs(nums, k)
mx := 0

for i := k - 1; i < len(nums) - k; i++ {
for a := range A[i] {
for b := range B[len(nums) - i - 2] {
if a ^ b > mx {
mx = a ^ b
}
}
}
}
return mx
}

func reverse(nums []int) {
for i, j := 0, len(nums)-1; i < j; i, j = i+1, j-1 {
nums[i], nums[j] = nums[j], nums[i]
}
}

###C

typedef struct {
    int key;
    UT_hash_handle hh;
} HashItem; 

HashItem *hashFindItem(HashItem **obj, int key) {
    HashItem *pEntry = NULL;
    HASH_FIND_INT(*obj, &key, pEntry);
    return pEntry;
}

bool hashAddItem(HashItem **obj, int key) {
    if (hashFindItem(obj, key)) {
        return false;
    }
    HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
    pEntry->key = key;
    HASH_ADD_INT(*obj, key, pEntry);
    return true;
}

void hashFree(HashItem **obj) {
    HashItem *curr = NULL, *tmp = NULL;
    HASH_ITER(hh, *obj, curr, tmp) {
        HASH_DEL(*obj, curr);  
        free(curr);
    }
}

void findORs(int* nums, int numsSize, int k, HashItem** dp) {
    HashItem *prev[k + 1];
    for (int i = 0; i <= k; i++) {
        prev[i] = NULL;
    }
    hashAddItem(&prev[0], 0);
    for (int i = 0; i < numsSize; ++i) {
        for (int j = fmin(k - 1, i + 1); j >= 0; --j) {
            for (HashItem *pEntry = prev[j]; pEntry; pEntry = pEntry->hh.next) {
                int x = pEntry->key;
                hashAddItem(&prev[j + 1], x | nums[i]);
            }
        }
        for (HashItem *pEntry = prev[k]; pEntry; pEntry = pEntry->hh.next) {
            int x = pEntry->key;
            hashAddItem(&dp[i], x);
        }
    }
    for (int i = 0; i <= k; i++) {
        hashFree(&prev[i]);
    }
};

void reverse(int *nums, int numsSize) {
    for (int i = 0, j = numsSize - 1; i < j; i++, j--) {
        int x = nums[i];
        nums[i] = nums[j];
        nums[j] = x;
    }
}

int maxValue(int* nums, int numsSize, int k) {
    HashItem *A[numsSize];
    HashItem *B[numsSize];

    for (int i = 0; i < numsSize; i++) {
        A[i] = B[i] = NULL;
    }
    findORs(nums, numsSize, k, A);
    reverse(nums, numsSize);
    findORs(nums, numsSize, k, B);
    int mx = 0;
    for (size_t i = k - 1; i < numsSize - k; ++i) {
        for (HashItem *pEntry = A[i]; pEntry; pEntry = pEntry->hh.next) {
            int a = pEntry->key;
            for (HashItem *pEntry = B[numsSize - i - 2]; pEntry; pEntry = pEntry->hh.next) {
                int b = pEntry->key;
                mx = fmax(mx, a ^ b);
            }
        }
    }
    for (int i = 0; i < numsSize; i++) {
        hashFree(&A[i]);
        hashFree(&B[i]);
    }
    return mx;
}

###JavaScript

var maxValue = function(nums, k) {
    function findORs(nums, k) {
        const dp = [];
        const prev = Array.from({ length: k + 1 }, () => new Set());
        prev[0].add(0);

        for (let i = 0; i < nums.length; i++) {
            for (let j = Math.min(k - 1, i + 1); j >= 0; j--) {
                for (const x of prev[j]) {
                    prev[j + 1].add(x | nums[i]);
                }
            }
            dp.push(new Set(prev[k]));
        }
        return dp;
    }

    const A = findORs(nums, k);
    nums.reverse();
    const B = findORs(nums, k);
    let mx = 0;

    for (let i = k - 1; i < nums.length - k; i++) {
        for (const a of A[i]) {
            for (const b of B[nums.length - i - 2]) {
                mx = Math.max(mx, a ^ b);
            }
        }
    }
    return mx;
};

###TypeScript

function maxValue(nums: number[], k: number): number {
    function findORs(nums: number[], k: number): Set<number>[] {
        const dp: Set<number>[] = [];
        const prev: Set<number>[] = Array.from({ length: k + 1 }, () => new Set());
        prev[0].add(0);

        for (let i = 0; i < nums.length; i++) {
            for (let j = Math.min(k - 1, i + 1); j >= 0; j--) {
                for (const x of prev[j]) {
                    prev[j + 1].add(x | nums[i]);
                }
            }
            dp.push(new Set(prev[k]));
        }
        return dp;
    }

    const A = findORs(nums, k);
    nums.reverse();
    const B = findORs(nums, k);
    let mx = 0;

    for (let i = k - 1; i < nums.length - k; i++) {
        for (const a of A[i]) {
            for (const b of B[nums.length - i - 2]) {
                mx = Math.max(mx, a ^ b);
            }
        }
    }
    return mx;
};

###Rust

use std::collections::HashSet;
use std::cmp::{max, min};

impl Solution {
    pub fn max_value(nums: Vec<i32>, k: i32) -> i32 {
        fn find_ors(nums: &Vec<i32>, k: i32) -> Vec<HashSet<i32>> {
            let mut dp = Vec::new();
            let mut prev = vec![HashSet::new(); k as usize + 1];
            prev[0].insert(0);

            for i in 0..nums.len() {
                for j in (0..= min(k as usize - 1, i + 1)).rev() {
                    let (before, after) = prev.split_at_mut(j + 1);
                    for &x in &before[j] {
                        after[0].insert(x | nums[i]);
                    }
                }
                dp.push(prev[k as usize].clone());
            }
            dp
        }

        let a = find_ors(&nums, k);
        let reversed_nums: Vec<i32> = nums.iter().rev().cloned().collect();
        let b = find_ors(&reversed_nums, k);
        let mut mx = 0;
        for i in k as usize - 1..nums.len() - k as usize {
            for &a_val in &a[i] {
                for &b_val in &b[nums.len() - i - 2] {
                    mx = mx.max(a_val ^ b_val);
                }
            }
        }
        mx
    }
}

复杂度分析

  • 时间复杂度:$O(n \times k \times U + n \times U^2)$,其中 $n$ 是数组 $\textit{nums}$ 的长度,$U$ 是数组元素的可能性集合大小。$\textit{dp}$ 的状态有 $O(n\times k)$ 种,每个状态消耗 $O(U)$ 计算。最后两两求异或消耗 $O(n\times U^2)$ 的时间。

  • 空间复杂度:$O(n \times U)$。

每日一题-求出数组中最大序列值🔴

2025年1月18日 00:00

给你一个整数数组 nums 和一个  整数 k 。

定义长度为 2 * x 的序列 seq 的  为:

  • (seq[0] OR seq[1] OR ... OR seq[x - 1]) XOR (seq[x] OR seq[x + 1] OR ... OR seq[2 * x - 1]).

请你求出 nums 中所有长度为 2 * k 的 子序列最大值 。

 

示例 1:

输入:nums = [2,6,7], k = 1

输出:5

解释:

子序列 [2, 7] 的值最大,为 2 XOR 7 = 5 。

示例 2:

输入:nums = [4,2,5,6,7], k = 2

输出:2

解释:

子序列 [4, 5, 6, 7] 的值最大,为 (4 OR 5) XOR (6 OR 7) = 2 。

 

提示:

  • 2 <= nums.length <= 400
  • 1 <= nums[i] < 27
  • 1 <= k <= nums.length / 2
❌
❌