最少操作次数

本文探讨如何通过最少步骤将一个字符串中的字符移动至开头,实现从初始字符串到目标字符串的转换。通过分析字符串特性,揭示解题关键并提供算法实现。

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

之余看到pongo网上有这么一题,便想了一下,其实比我想象的要简单。不是学生,没有在pongo网上测试

题目:给定两个字符串,仅由小写字母组成,它们包含了相同字符。 求把第一个字符串变成第二个字符串的最小操作次数,且每次操作只能对第一个字符串中的某个字符移动到此字符串中的开头。 例如给定两个字符串“abcd" "bcad" ,输出:2,因为需要操作2次才能把"abcd"变成“bcad" ,方法是:abcd->cabd->bcad。


最开始时看到这题想可能要用到递归吧,其实这题可以巧解。

对于str1 = "abcd",str2 =“bcad”这个测试用例讲解一下

strlen(str1) = strlen(str2) = 4

其实需要先理解对于任意两个字符串str1, str2,操作次数最多需要strlen(str1) - 1(这个应该很简单看出来),既然这样我们先构造一个需要最多操作次数两字符串。举几个例子,观察一下

str1 = “abdc”, str2 = "abcd"

str1 = “badc”, str2 = "abcd"

str1 = “bdca”, str2 = "abcd"

str1 = “bdac”, str2 = "abcd"

......

这些都是需要3次操作的。它们有什么共同的特征了(这是解题的关键),str2的最后两个字符是‘d’和‘c’

在str1中字符串只要是“***d***c***”形式,就是‘d’在‘c’前面,就需要最多操作次数。为什么了?原因是,对于此时的

str1,str2,第一次移动str1必定是移动‘c’到最前面,那么剩下的的字符(除d’和‘c’),都需要按一定顺序移动到最前面即可,所以加

起来便是1 + strlen(str1) - 2 = strlen(str1) - 1 。

那么当str2 = “abcd”时,str1中的‘c’在‘d’前面时,这种情况需要多少次了,此时操作次数是去掉str1和str2中的‘d’剩下的字符需要操作的次数。

对于题目原始的列子str1 = "abcd",str2 =“bcad"

同str1= “abc”, str2 = “bca”的操作次数相同,此时的移动次数为2(不用再解释了吧,str1中‘c’在‘a’后面)。

剩下就是写代码了,讲到这里想必大家都知道该怎么写了,我把我的代码贴出来,我是考虑到字符串中可能有重复的字符,所以从后面遍历的了


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int getNum(const char * str1, const char * str2)
{
   int len = strlen(str2);
   char * str3 = strdup(str1);
   for(int i = len - 1; i > 0; i--)
   {
	   for(int j = len - 1; j > 0; j--)
	   {
			if(str3[j] == str2[i])
			{
				str3[j] = '\0';
				break;
			}
			else if(str3[j] == str2[i-1])
			{
				free((void *)str3);
				return i;
			}
	   }
   }
   free((void *)str3);
   return 0;
}

int main()
{    
    printf("%d\n",getNum("bdac", "bdac"));
}





### Java算法实现:使矩阵每列严格递增所需的最少操作次数 为了实现在Java中找到使矩阵每一列都严格递增所需要的最小操作数量,可以采用贪心策略来解决问题。对于给定的一个整数矩阵`matrix`,目标是通过增加某些元素使得每一列中的数值都是严格上升的。 #### 方法概述 该方法的核心在于逐行遍历并记录当前处理到的最大值,在遇到满足条件的情况时更新计数器以及调整最大值列表以适应新的约束[^1]。 #### 实现细节 下面是一个具体的解决方案: ```java import java.util.*; public class MatrixColumnIncrement { public static int minOperations(int[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int rows = matrix.length, cols = matrix[0].length; List<Integer> maxInCols = new ArrayList<>(Collections.nCopies(cols, Integer.MIN_VALUE)); int operationsCount = 0; for (int row = 0; row < rows; ++row){ for (int col = 0; col < cols; ++col){ if(matrix[row][col] <= maxInCols.get(col)){ // Increment operation count when adjustment is required. operationsCount += Math.abs(maxInCols.get(col) - matrix[row][col]) + 1; matrix[row][col] = maxInCols.get(col) + 1; } // Update maximum value encountered so far in current column. maxInCols.set(col, Math.max(maxInCols.get(col), matrix[row][col])); } } return operationsCount; } public static void main(String[] args) { int[][] matrix = {{1,2,3},{2,2,4},{3,2,5}}; System.out.println(minOperations(matrix)); // Output should be the minimal number of changes made. } } ``` 此程序定义了一个名为 `minOperations` 的函数,它接收一个二维数组作为参数,并返回将所有列变为严格递增序列所需执行的操作数目。此外还提供了一个简单的测试案例用于展示如何调用上述功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值