477. Total Hamming Distance

此篇博客讲解如何通过编程解决一个实际问题:给定一个整数数组,求所有元素之间的汉明距离之和。算法涉及遍历每位、统计0和1的个数,并应用组合公式。适用于解决与二进制表示和离散数学有关的问题。

The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

Given an integer array nums, return the sum of Hamming distances between all the pairs of the integers in nums.

Example 1:

Input: nums = [4,14,2]
Output: 6

Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just
showing the four bits relevant in this case).
The answer will be:
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.
Example 2:

Input: nums = [4,14,4]
Output: 4

Constraints:

  • 1 <= nums.length <= 104
  • 0 <= nums[i] <= 109
  • The answer for the given input will fit in a 32-bit integer.

给出的数字都在 32 位整数之内, 我们可以把每一位为 0 和为 1 的数字数量分别统计出来,假设为 0 的是 n 个, 那为 1 的就是 length - n 个, 那他们对整体距离的贡献就是 n * (length -n)


impl Solution {
    pub fn total_hamming_distance(nums: Vec<i32>) -> i32 {
        let mut total = 0;
        for i in 0..32 {
            let mut ones = 0;
            let mut zeros = 0;
            let mask = 1 << i;
            for j in 0..nums.len() {
                if nums[j] & mask > 0 {
                    ones += 1;
                } else {
                    zeros += 1;
                }
            }
            total += ones * zeros;
        }
        total
    }
}
f = { 0: { '0': 2, '1': 1 }, 1: { '00': 2, '01': 3, '10': 2, '11': 0 }, 2: { '000': 0, '001': 1, '010': 1, '011': 0, '100': 2, '101': 0, '110': 0, '111': 0 } } import random def generate_sequence(N): # TODO ''' generates an N random bits (0, 1) sequence Parameters: ----------- N : number of bits in the sequence Returns: -------- sequence: sequence of N bits ''' sequence=[] for i in range(N) : sequence.append(random.choice(['0', '1'])) # generate a random sequence of N bits (0, 1) return sequence def compute_fitness(sequence, K): # TODO ''' computes the fitness of sequence, with respect to K, according to table f Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- fitness: fitness value of sequence ''' seq = str(sequence) N = len(seq) fitness = 0 if K == 0: # f0: 0->2, 1->1 for bit in seq: fitness += 2 if bit == '0' else 1 elif K == 1: # f1: 00->2, 01->3, 10->2, 11->0 for i in range(N): pair = seq[i] + seq[(i+1) % N] if pair == '00': fitness += 2 elif pair == '01': fitness += 3 elif pair == '10': fitness += 2 elif K == 2: # f2: 000->0 001->1 010->1 011->0 100->2 101->0 110->0 111->0 for i in range(N): triple = seq[i] + seq[(i+1) % N] + seq[(i+2) % N] if triple == '001' or triple == '010': fitness += 1 elif triple == '100': fitness += 2 return fitness def neighbors(sequence): ''' returns all neighbors of sequence () Parameters: ----------- sequence : N-bits sequence Returns: -------- generator of neighbors of sequence ''' for i in range(len(sequence)): if sequence[i] == '0': new = '1' else: new = '0' yield (sequence[:i] + new + sequence[i + 1:]) # generate all neighbors that differ in 1 bit def mean_steps(samples): ''' returns mean of steps taken to find solution (for deterministic) Parameters: ----------- samples : samples of deterministic_hillclimb runs Returns: -------- mean steps ''' # get mean of steps needed to find solution (sum of samples' steps/number of samples) return sum(x[2] for x in samples)/len(samples) def generate_samples(hillclimb_method, K): ''' generates 50 samples (solutions) for the hillclimb method (deterministic/probabilistic) Parameters: ----------- hillclimb_method : deterministic_hillclimb/probabilistic_hillclimb K : parameter K (0, 1, or 2) Returns: -------- generator of samples/solutions (sequence, fitness, number of steps) ''' if K not in [0, 1, 2]: raise Exception("Invalid K") # run for 50 times to get 50 samples/solutions for i in range(50): # generate initial sequence initial_sequence = generate_sequence(N=21) # get solution, its fitness, number of steps taken to find solution x, f_x, s = hillclimb_method(initial_sequence, K) yield (x, f_x, s) def deterministic_hillclimb(sequence, K): # TODO ''' performs deterministic_hillclimb Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- sequence : optimal/fittest sequence found max_fitness : fitness value of sequence steps: steps it took to reach optimum ''' current_solution = sequence current_value = compute_fitness(current_solution, K) steps = 0 # 记录每次迭代的最佳值 best_values = [current_value] # 迭代寻找更好的解 for i in range(50): # 最多迭代50次 # 生成邻近解 neighbor = neighbors(current_solution,K) neighbor_value = compute_fitness(neighbor, K) # 如果邻近解更优,则更新当前解 if neighbor_value < current_value: current_solution = neighbor current_value = neighbor_value else: pass # 没有改进,保持当前解不变 best_values.append(current_value) # 记录当前最佳值 return current_solution, current_value, best_values # dictionary to save deterministic_hillclimb samples (sequence, max_fitness, steps) deterministic_samples = {} # dictionary to save number of steps to perform probabilistic hillclimb probabilistic_steps = {} # run deterministic_hillclimb, get mean steps for K in [0, 1, 2]: # for each K, generate 50 deterministic_hillclimb solutions, and save them deterministic_samples[K] = list(generate_samples(deterministic_hillclimb, K)) # for each K, save the number of steps to take (10*mean steps taken for deterministic_hillclimb) probabilistic_steps[K] = 10*round(mean_steps(deterministic_samples[K])) def probabilistic_hillclimb(sequence, K): # TODO ''' performs probabilistic_hillclimb Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- sequence : optimal/fittest sequence found max_fitness : fitness value of sequence steps: steps corresponding to parameter K ''' current_solution = sequence current_value = compute_fitness(current_solution, K) steps = 0 max_iterations = probabilistic_steps[K] import numpy as np for _ in range(max_iterations): # Generate all neighbors neighbor_list = [] for i in range(len(current_solution)): neighbor = list(current_solution) neighbor[i] = '1' if neighbor[i] == '0' else '0' neighbor_list.append(''.join(neighbor)) neighbor_values = [compute_fitness(neighbor, K) for neighbor in neighbor_list] # Calculate selection probabilities (higher fitness gets higher probability) total = sum(neighbor_values) if total == 0: probabilities = [1/len(neighbor_values)] * len(neighbor_values) else: probabilities = [v/total for v in neighbor_values] # Randomly select a neighbor based on probabilities selected_index = np.random.choice(len(neighbor_list), p=probabilities) selected_neighbor = neighbor_list[selected_index] selected_value = neighbor_values[selected_index] # Update current solution if better if selected_value > current_value: current_solution = selected_neighbor current_value = selected_value steps += 1 return current_solution, current_value, steps # dictionary to save probabilistic_hillclimb samples (sequence, max_fitness, steps) probabilistic_samples = {} # run probabilistic_hillclimb for K in [0, 1, 2]: # for each K, generate 50 probabilistic_hillclimb solutions, and save them probabilistic_samples[K] = list(generate_samples(probabilistic_hillclimb, K)) def hamming_distance(sequence1, sequence2): # TODO ''' returns hamming distance between sequence1 and sequence2 Parameters: ----------- sequence1 : N-bits sequence sequence2 : N-bits sequence Returns: -------- distance : hamming distance between sequence1 and sequence2 ''' xor_result = sequence1 ^ sequence2 return bin(xor_result).count('1') import matplotlib.pyplot as plt # 分析并绘制汉明距离 def analyze_and_plot_hamming(N=21, num_runs=50): # 存储结果 hamming_results = {} for K in [0, 1, 2]: print(f"处理 K={K}") hamming_results[K] = {'deterministic': [], 'probabilistic': []} # 存储解 det_solutions = [] prob_solutions = [] # 运行实验 for run in range(num_runs): seq = generate_sequence(N) # 确定性爬山 det_sol, _, _ = deterministic_hillclimb(seq, K) det_solutions.append(det_sol) # 概率性爬山 prob_sol, _, _ = probabilistic_hillclimb(seq, K) prob_solutions.append(prob_sol) # 计算汉明距离 hamming_results[K]['deterministic'] = get_all_hamming_distances(det_solutions) hamming_results[K]['probabilistic'] = get_all_hamming_distances(prob_solutions) # 绘制结果 plot_hamming_results(hamming_results) return hamming_results # 计算所有解对之间的汉明距离 def get_all_hamming_distances(solutions): distances = [] n = len(solutions) for i in range(n): for j in range(i+1, n): dist = hamming_distance(solutions[i], solutions[j]) distances.append(dist) return distances 这是我的全部的代码,请编写 Plot and analyze pairwise hamming distances for all methods and K values的答案代码
最新发布
09-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值