递归字符串反转函数
Posted
技术标签:
【中文标题】递归字符串反转函数【英文标题】:recursive string reverse function 【发布时间】:2011-03-26 08:53:38 【问题描述】:出于好奇,编写了一个,但在那里的 XOR 有点问题。这个函数的重点是不使用迭代器,这就是为什么它是一个递归函数。这不是作业,只是好奇。
private static char[] ReverseNL(char[] arr, int index)
var len = arr.Length;
if (index > 0)
arr[len - index] ^= arr[index - 1];
return index-- < 1 ? arr : ReverseNL(arr, index);
我的字符串的第一部分似乎卡住了
“嘿,堆栈!”变成“I♫→A ←E↨reht yeh”
总是词组的前半部分变得混乱......
更新..
我想这里真的不需要 XOR.. 所以使用了基本赋值,也摆脱了 return。
private static void ReverseNL(char[] arr, int index)
var len = arr.Length;
if (index > 0 && index > len / 2)
var c = arr[len - index];
arr[len - index] = arr[index - 1];
arr[index - 1] = c;
index--;
ReverseNL(arr, index);
【问题讨论】:
@NullUserException - 显然已经足够大,可以在问题中引用南方公园的一首歌曲(是否合适是另一个问题)。 我建议您将字符串更改为更标准的短语,例如:“The quick brown fox jumps over the lazy dog” 我认为您想要执行交换,并且您正在尝试执行 XOR 交换(由于算法错误而失败)。只需使用简单的交换;对于那些不完全理解它是如何工作的人来说,异或交换肯定会导致混乱。 或者是回文,比如“aibohphobia”? 你知道异或运算符的作用吗?看起来你认为它会交换你的字符,这就是它的作用: 10110110 XOR 00011100 变为: 10101010 因此你会得到 mumbo jumbo 【参考方案1】:递归几乎总是用来简化问题。递归算法通常在本质上也是函数式的(尽管它们并非必须如此)。
在反转字符串(或char[]
)的情况下,“更简单”意味着“在更小的数组上操作”。
例如,你可以按如下方式减少:
"test"
"est" 't'
"st" 'e'
"t" 's'
"" 't'
(左边是减少的数据;右边是剪切的数据)。
在伪代码中,您可以按如下方式进行归约:
char[] reverse(char[] data)
if (data.Count() == 0)
return new char[] ;
char cut = data.First();
char[] rest = data.Skip(1);
char [] restReversed = reverse(rest);
// ???
我会留给你来决定接下来需要对你拥有的数据做什么。
【讨论】:
【参考方案2】:可能不是最有效的,但这应该会给你一些关于如何让递归工作的想法......
static string ReverseNL (string s)
if ((s == null) || (s.Length <= 1))
return s;
return ReverseNL(s.Substring(1)) + s[0];
static void Main(string[] args)
string src = "The quick brown fox";
Console.WriteLine(src);
src = ReverseNL(src);
Console.WriteLine(src);
【讨论】:
实际上我认为这是我最喜欢的解决方案,因为它只有 3 行。简洁大方。【参考方案3】:如果你想要一个使用 XOR 和递归的解决方案,试试这个:
private static void ReverseNL(char[] arr, int index)
if (index <arr.Length/2)
arr[index] ^= arr[arr.Length - index-1];
arr[arr.Length - index-1] ^= arr[index ];
arr[index] ^= arr[arr.Length - index-1];
ReverseNL(arr,++index);
您不需要返回任何内容,因为所有内容都在数组中完成。当然,您可以只删除 XOR 部分并交换元素,但这更酷。 ;)
(编辑:索引应该从 0 开始)
【讨论】:
【参考方案4】:一个观察:您正在操作并返回一个数组。总是相同的数组。数组始终是引用。
这意味着您的退货声明过于复杂且具有误导性。在所有情况下都以return arr;
结尾。
考虑一般提示的那一部分:让它更简单,你会更容易看到错误。仅在 return 语句中的 --
就应该引发危险。
// untested, simplified return
private static char[] ReverseNL(char[] arr, int index)
var len = arr.Length;
if (index > 0)
arr[len - index] ^= arr[index - 1];
// return index-- < 1 ? arr : ReverseNL(arr, index);
if (index >= 1)
ReverseNL(arr, index-1);
return arr;
【讨论】:
我看不出我的 return 语句有什么问题。我可以把它分成几行,但它会做同样的事情。如果 index 为 0,则返回 arr,否则递归。该部分已经过测试并且工作正常。 @Sonic:你正在原地倒车。你根本不需要退货。如果你确实使用 return 它独立于递归是/否。【参考方案5】:在这个特定的例子中,我宁愿这样做:
return arr.Reverse();
【讨论】:
谢谢,但我没有要求反转字符串的最佳方法。这只是一个好奇心练习 当然,作业结果应该要求尽可能简洁的答案...... 这不是家庭作业。我曾经在一次采访中被问到这个问题,但不需要编写代码。所以现在出于好奇而写它。 @Sonic Soul,在我看来,这仍然属于“家庭作业”的范畴。您需要在正确的方向上轻轻推动以使您回到正轨,而不是问题的完整答案。【参考方案6】:XOR 必须被调用两次才能交换一对元素。它只在数组的前半部分被调用一次。 (编辑中:严格来说,每次赋值只调用一次,所以净效果就像对一半数组进行两次异或交换。)
【讨论】:
以上是关于递归字符串反转函数的主要内容,如果未能解决你的问题,请参考以下文章