我陷入了这种 c++ 语法中。 “检查一个数字中所有数字的频率是不是相同”
Posted
技术标签:
【中文标题】我陷入了这种 c++ 语法中。 “检查一个数字中所有数字的频率是不是相同”【英文标题】:I got stuck in this syntax of c++. "Check if the frequency of all the digits in a number is same"我陷入了这种 c++ 语法中。 “检查一个数字中所有数字的频率是否相同” 【发布时间】:2020-09-13 00:29:49 【问题描述】:我正在练习“检查一个数字中所有数字的频率是否相同”的编码问题
#include<bits/stdc++.h>
using namespace std;
// returns true if the number
// passed as the argument
// is a balanced number.
bool isNumBalanced(int N)
string st = to_string(N);
bool isBalanced = true;
// frequency array to store
// the frequencies of all
// the digits of the number
int freq[10] = 0;
int i = 0;
int n = st.size();
for (i = 0; i < n; i++)
// store the frequency of
// the current digit
freq[st[i] - '0']++;
for (i = 0; i < 9; i++)
// if freq[i] is not
// equal to freq[i + 1] at
// any index 'i' then set
// isBalanced to false
if (freq[i] != freq[i + 1])
isBalanced = false;
// return true if
// the string is balanced
if (isBalanced)
return true;
else
return false;
// Driver code
int main()
int N = 1234567890;
bool flag = isNumBalanced(N);
if (flag)
cout << "YES";
else
cout << "NO";
但我看不懂这段代码:
//存储频率 // 当前数字 频率[st[i] - '0']++;
这部分如何实际工作和存储频率? 除了这一行,我还能写什么?
【问题讨论】:
既然您问的是显示的代码是如何工作的,那么它一定不是您的代码,而是您从其他地方获得的代码(顺便说一下,这显示了许多糟糕的编程实践)。这是另一个例子,学习 C++ 的唯一方法是使用教科书,而不是一些 Youtube 视频或在线黑客网站。显示的代码设计过度且相当复杂,正确的方法大约需要显示代码的三分之一,并且不涉及到std::string
的任何无用转换,而只是一些简单的数学运算。无论代码来自哪里,这都是一个不好学习的例子。
这一行发生了几件事。有数组访问,有减法,有从char
到int
的整数提升(我猜是std::size_t
),还有一元递增(++
)。把大象分成几口。
Why is “using namespace std;” considered bad practice?
Why should I not #include <bits/stdc++.h>
?
你的话:“我看不懂这段代码:”。这很麻烦,因为它应该是 your 代码。投票结束。只关注一个问题。
【参考方案1】:
st
是一个字符串,因此是char
s 的序列。 st[i]
是该字符串中的第 i 个字符。
字符实际上是 0 到 256 之间的正整数,因此您可以将它们用于数学运算,例如 -
。这些整数根据ASCII 字母分配给字符。例如:char 0
赋值为 48,char 7
赋值为 55(注:以下我用x
表示字符)。
它们的顺序使得数学运算如下所示成为可能:char 7
和 char 0
正好相隔 7 个数字,因此 0
+ 7 = 48 + 7 = 55 = 7
。所以:7
- 0
= 7。
因此,您可以根据数字获得 freq
数组中的位置,即位置 0 表示 0 或位置 7 表示 7。++
运算符就地递增该值。
【讨论】:
除了这一行,我还能写什么? 我认为,这行在它的上下文中是好的。您可以将其拆分为多个表达式以使其更易于理解,但对于有经验的 C++ 用户来说,这是非常常见的代码。因此,了解这条线的含义很重要。整个问题的更好解决方案不是将数字转换为字符串,而是使用除法和模数直接计算整数范围内数字的频率。下面也提出了这样的解决方案。【参考方案2】:这一行是几件事浓缩成一个表达式
freq[st[i] - '0']++;
个别部分比较简单,总体来说也不是太难:
st[i] - '0'
- 字符数字不会将 1 到 1 映射到整数。有一个偏移量。 '1'
的整数值为1 + '0'
,'2'
为2 + '0'
。因此,要从数字中获取整数,您需要减去 '0'
。
freq[ ... ]
- 访问数组的元素。索引i
处的元素存储数字i
的频率。
()++
- 将该频率增加一。
【讨论】:
@LajosArpad 鉴于 OP 甚至不知道代码应该做什么,我觉得将答案称为“正确”有点大胆。 @TedLyngmo 问题是指代码的一部分并要求我们解释它。当我将此答案称为“正确”时,我的意思是,具有该语言基本知识但对问题中概述的代码块感到困惑的人应该有一个heureka时刻阅读答案。我发现你质疑我对这个问题的解释很大胆。这个问题以一种非常清晰的方式显示了一小部分代码,对于提问者来说是不清楚的。如果我们试图谦虚和友善,那么你和我当然都理解这个问题。 @LajosArpad 我喜欢你在问题和/或答案中找到快乐。我也很喜欢 idclev 的答案——我读过很多。我刚刚发现这个特殊的(和我的许多人一样)是在黑暗中拍摄的。它可能非常适合 OP,也可能不适合。我觉得这个问题不像你描述的那么清楚。 “如果我们试着谦虚和友善,那么你和我当然都理解这个问题” - 我同意这种观点,但我仍然没有完全理解这个问题。正如我在问问题时问 OP... @idclev463035818 让我们定义什么是基础知识。他/她知道如何定义变量,一般是什么类型,并且使用过几次数组。带有字符的算术计算对您来说似乎是基本的,因为您可能已经这样做了很多年。但对于渴望学习的人来说,情况并非如此。为了理解 st[i] - '0' 是转换为用作索引的数字,有人需要的不仅仅是基本的理解。 @LajosArpad 我删除了我的 cmets,这一切真的不属于这里。我同意泰德的观点,即您的评论不是很有用。您本可以指出我的错别字或建议改进,但“另一个正确答案”。只是让我想知道,你怎么知道?【参考方案3】:从单个字符串字符中减去“0”字符会得到您要查找的实际数字。这为您提供了您在代码中跟踪其频率的数字。这是因为字符存储为 ASCII 值的方式。查看下表。假设传入的整数值N
是 1221。在此示例中观察到的第一个值是“1”,它对应于 ASCII 值 49。“0”的 ASCII 值是 48。减去两者:49 - 48 = 1。这允许您将每个整数值作为数组的一部分单独访问,该数组是将“int”值转换为字符串的结果。
ASCII Table
【讨论】:
@LajosArpad 你确定你对问题的解释是正确的吗? @TedLyngmo 让我们不要用我们在另一个线程中进行的相同讨论来垃圾邮件这个答案。不得不对这种挑剔和傲慢的评论做出反应,我不会做两次。 @LajosArpad 我同意。为什么不删除这些额外的“是的,这是正确的”和“不,我不这么认为”的 cmets?`我都在。 @TedLyngmo 同意其他回答者并不是多余的,因为其他回答者是不同的人。你对我的同意吹毛求疵是多余的。 @LajosArpad 我同意和不同意其他回答者,并且被同一个人投票赞成和反对。我们互相编辑并互相帮助以得到一个好的答案——通常是在回答同一个问题时。这就是我发现这里的动力。我从中学到了很多。在 cmets 有额外的。如果评论声称答案是正确的,则需要对其提出质疑 - 或将其转化为答案 - 如果该声明显然不是完美的。【参考方案4】:代码
for (i = 0; i < n; i++)
// store the frequency of
// the current digit
freq[st[i] - '0']++;
遍历字符串,对每一项减去'0',其值为48,因为字符码48代表0,字符码49代表1,以此类推。
然而,这段代码是多余的,在存储字符串时会浪费内存,并且会浪费时间将数字转换为字符串。这样更好:
bool isNumBalanced(int N)
//We create an array of 10 for each digit
int digits[10];
//Initialize the difits
for (int i = 0; i < 10; i++) digits[i] = 0;
//If the input is 0, then we have a trivial case
if (N == 0) return true;
//We loop the digits
do
//N % 10 is the last digit
//We increment the frequency of that digit
digits[N % 10]++;
while ((N /= 10) != 0); //We don't stop until we reach the trivial case, see above
//Using the transitivity of equality, we compare all values to the first
//We return false upon the first difference
for (int j = 1; j < 10; j++)
if (digits[0] != digits[j]) return false;
//Otherwise we return true
return true;
【讨论】:
并不重要,但是将每个元素与第一个元素进行比较或将每个元素与下一个元素进行比较都没有区别 @idclev463035818 不同的是我不需要把数字转成字符串,浪费内存和处理能力。【参考方案5】:对于那些不明白的人。
int arr[5]=0 // it stores 0 in all places
for(int i=0;i<5;i++)
arr[i]++;
// Now the array is [1 1 1 1 1]
这里发生的首先是 i=0 然后 arr[0]++ “这里 arr[0] 的值是 0,++,它从 0 增加到 1” 现在 arr[0] 值为 1。 现在` 让
st="1221";
for (i = 0; i < 4; i++)
freq[st[i] - '0']++;
for i=0, the freq location is : freq[49-48]++ = freq[1]++ means value of freq[1] is 1
for i=1, the freq location is : freq[50-48]++ = freq[2]++ means value of freq[2] is 1
for i=2, the freq location is : freq[50-48]++ = freq[2]++ means value of freq[2] is 2
for i=3, the freq location is : freq[49-48]++ = freq[1]++ means value of freq[1] is 2
'0' 的 ASCII 值是 48
'1' 的 ASCII 值是 49
'2'的ASCII值是50
【讨论】:
以上是关于我陷入了这种 c++ 语法中。 “检查一个数字中所有数字的频率是不是相同”的主要内容,如果未能解决你的问题,请参考以下文章