第144场双周赛题解:两个字符串得切换距离

ops/2024/11/29 2:08:11/

leetcode.cn/contest/biweekly-contest-144/problems/shift-distance-between-two-strings/" rel="nofollow">两个字符串得切换距离

1、题目描述

给你两个长度相同的字符串 st ,以及两个整数数组 nextCostpreviousCost

一次操作中,你可以选择 s 中的一个下标 i ,执行以下操作 之一 :

  • s[i] 切换为字母表中的下一个字母,如果 s[i] == 'z' ,切换后得到 'a' 。操作的代价为 nextCost[j] ,其中 j 表示 s[i] 在字母表中的下标。
  • s[i] 切换为字母表中的上一个字母,如果 s[i] == 'a' ,切换后得到 'z' 。操作的代价为 previousCost[j] ,其中 js[i] 在字母表中的下标。

切换距离 指的是将字符串 s 变为字符串 t 的 最少 操作代价总和。

请你返回从 st切换距离

2、解题思路

1、字符与字母表的映射
  • 字母表有 26 个字母,从 'a''z'
  • 每个字符都有对应的下标 index,计算公式为: i n d e x = o r d ( c ) − o r d ( a ) index=ord(c)−ord(a) index=ord(c)ord(a)
2、切换规则
  • 从字符 s[i] 到 ,可能需要:
    1. 顺时针切换(下一个字母)。
    2. 逆时针切换(上一个字母)。
  • 字符切换可能经过 0 到 25 个字母,因此需要考虑两种切换的代价并取较小值。
3、代价计算
  • 对于顺时针切换: c o s t = n e x t c o s t [ i n d e x ( s [ i ] ) ] + … + n e x t c o s t [ i n d e x ( t [ i ] ) ] cost=nextcost[index(s[i])]+…+nextcost[index(t[i])] cost=nextcost[index(s[i])]++nextcost[index(t[i])]
  • 对于逆时针切换: c o s t = p r e v i o u s c o s t [ i n d e x ( s [ i ] ) ] + … + p r e v i o u s c o s t [ i n d e x ( t [ i ] ) ] cost=previouscost[index(s[i])]+…+previouscost[index(t[i])] cost=previouscost[index(s[i])]++previouscost[index(t[i])]
4、贪心策略
  • 对于每对字符 ( s [ i ] , t [ i ] ) (s[i],t[i]) (s[i],t[i]),计算顺时针和逆时针切换的代价,选择较小值。

3、代码实现

class Solution {
public:long long shiftDistance(string s, string t, vector<int>& nextCost, vector<int>& previousCost) {int n = s.size();int alphabetSize = 26;   // 字母表大小long long totalCost = 0; // 使用 long long 防止溢出for (int i = 0; i < n; ++i) {int start = s[i] - 'a'; // 起始字符的下标int end = t[i] - 'a';   // 目标字符的下标// 计算顺时针代价long long clockwiseCost = 0;for (int j = start; j != end; j = (j + 1) % alphabetSize) {clockwiseCost += nextCost[j];}// 计算逆时针代价long long counterClockwiseCost = 0;for (int j = start; j != end; j = (j - 1 + alphabetSize) % alphabetSize) {counterClockwiseCost += previousCost[j];}// 累加到总代价中,选择顺时针和逆时针中的较小值totalCost += min(clockwiseCost, counterClockwiseCost);}return totalCost;}
};

关键点

  1. 代价累加使用 long long
    • totalCostclockwiseCostcounterClockwiseCost 均使用 long long 类型,防止溢出。
  2. 顺时针与逆时针的灵活计算
    • 顺时针使用 (j + 1) % alphabetSize
    • 逆时针使用 (j - 1 + alphabetSize) % alphabetSize

4、复杂度分析

  1. 时间复杂度
    • 对于每个字符对 ( s [ i ] , t [ i ] ) (s[i],t[i]) (s[i],t[i]),最多需要遍历 O(26) 次字母表。
    • 总时间复杂度为 O ( n × 26 ) = O ( n ) O(n×26)=O(n) O(n×26)=O(n)
  2. 空间复杂度
    • 仅使用常数额外空间。
    • 空间复杂度为 O(1) 。

http://www.ppmy.cn/ops/137532.html

相关文章

Python Flask快速开发网站

在Web开发领域,Python拥有多种优秀的Web框架,例如Django、Flask、Pyramid等。其中Flask是一个微型框架,核心代码非常精简,只包含了Web应用最基本的功能。这使得Flask非常轻量级,容易上手,适合快速开发小型Web应用。本文将介绍如何使用Flask快速搭建一个简单的网站。 © ivw…

基于python+django+vue.js开发的停车管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/pytho…

Vue前端面试进阶(五)

使用Element UI开发的实际项目 在实际项目中&#xff0c;我使用Element UI来快速构建用户界面。Element UI是一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面端组件库&#xff0c;它提供了丰富的UI组件&#xff0c;极大地提高了开发效率。然而&#xff0c;在使用过程中…

【linux】手搓线程池

【linux】进程池 线程池: 一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着 监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利…

替代Postman ,17.3K star!

现在&#xff0c;许多人都朝着全栈工程师的方向发展&#xff0c;API 接口的编写和调试已成为许多开发人员必备的技能之一。 工欲善其事&#xff0c;必先利其器。拥有一款优秀的 API 工具对于任何工程师来说都是极为重要的&#xff0c;它能够帮助我们高效地完成各种开发任务。 …

什么是JSON,有什么特点

什么是 JSON&#xff1f; JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。它基于 JavaScript 的子集&#xff0c;但独立于语言&#xff0c;被广泛用于服务器与 Web 应…

Mybatis控制台打印SQL执行信息(执行方法、执行SQL、执行时间)

文章目录 前言一、基本功能介绍1.1本章功能效果预览图: 二、可执行源码2.1 yaml基础配置2.2 MybatisAnalyzeSQLInterceptor实现SQL拦截 前言 SQL性能监控是一个程序必要的功能&#xff0c;通常我们可以使用数据库自带的客户端工具进行SQL性能分析。然而对于一些专业度不高的人…

性能测试调优之线程池的性能优化

做性能测试时&#xff0c;有些压测场景下TPS上不去&#xff0c;或者响应时间变长&#xff0c;或者直接出现一些连接 被拒绝的报错&#xff0c;这些都有可能是tomcat的连接池不够引起的。 连接池的概念 线程池&#xff1a;是一个管理线程集合的框架&#xff0c;它负责维护一个…