提问人:Leodero20 提问时间:8/16/2023 最后编辑:halferLeodero20 更新时间:9/5/2023 访问量:128
如何在 LeetCode 中使用指针 C 中的两个求和问题
How to use pointers in LeetCode Two Sum problem in C
问:
我是 LeetCode 的新手,我唯一的 C 语言背景是它的一门基础知识。我希望改进和学习更多。我认为我在这里的问题出在指针或 malloc 上。我该如何解决这个问题?
这是我的代码:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int *ans;
ans = (int*)malloc(2*sizeof(int));
*returnSize = 2;
for(int i=0; i<numsSize; i++){
for(int j=i++ ; j<numsSize; j++){
if( nums[i] + nums[j] == target ){
ans[0] = i;
ans[1] = j;
break;
}
}
}
return *ans;
}
这是错误:
第 207 行:字符 3:运行时错误:加载类型“int”的地址0x000000000001未对齐,这需要 4 字节对齐 [Serializer.c] 0x000000000001:注意:指针指向此处
根据我对指针的理解:
*ans[0] = i
应该将 i 的值(一个整数)分配给指针 ans[0] 指向的值。但是,这会产生错误“错误:一元'*'(有'int')的无效类型参数”。所以,我尝试了上面的代码。- 'return *ans' 应该返回数组 [i,j]?
答:
如果你在 C 语言中有一个指针,你可以使用类似 的运算符取消引用它(获取它所指向的对象)。或者,如果为多个对象分配了内存(例如通过),则可以使用where代表要检索的对象的偏移量来访问每个对象。但是,如果为负数或大于/等于为其分配的内存量,则超出边界访问内存,这是未定义的行为,并可能导致分段错误。int* ptr
*
*ptr
malloc()
*(ptr + i)
i
i
由于写作有点丑陋且难以阅读,因此您可以使用它来代替,它做同样的事情。*(ptr + i)
ptr[i]
*ans[0] = i
应该分配 i 的值
您可以使用 or or 来获得工作结果。这三个选项都是一样的,但我更喜欢最后一个,因为你有一个数组,而不仅仅是你的指针指向的单个元素。(如果它只是一个数组,你应该使用它来使其更容易阅读和理解它不是一个数组。*ans = i
*(ans + 0) = i
ans[0] = i
*ans
return *ans
应该返回数组 [i,j]
同样的问题又来了。当你像 一样取消引用它时,你不会返回整个数组,而只返回它指向的第一件事,即整数。相反,你应该.*ans
i
return ans;
在内部循环中,您使用 ,它确实设置为 ,然后递增 1。这不是你想要的行为,因为它会跳过一个完整的迭代,这可能会导致你跳过你要查找的值。对于第一次迭代,并且 和 是相同的,但问题表明情况并非如此。所以你可以在你的内部循环中使用。for
int j=i++
j
i
i
i
i
j
int j = i + 1
for
代码的其余部分应该可以工作,但可以改进一点。我想你想在你的语句中退出你的两个循环? 只存在内部循环,这不会给你带来错误的结果,因为问题描述指出“只有一个有效的答案存在”,但你可以立即退出。否则,您可以使用一些额外的变量或跳转到函数的末尾。for
break
if
break
return ans;
goto
而且你不会检查什么会返回你。如果它返回(尽管这可能不会发生),那么当您尝试取消引用时,您的程序将崩溃。malloc()
NULL
ans
问题没有说如果你没有找到有效的一对会发生什么,但我认为“只有一个有效答案存在”意味着总有一个有效答案,不多也不少。对于我的解决方案,我假设我可能找不到一对,并且只有在我实际找到一对时才分配和设置为。ans
*returnSize
2
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
*returnSize = 0;
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] + nums[j] == target) {
int* ans = malloc(2 * sizeof(int));
if (ans != NULL) {
*returnSize = 2;
ans[0] = i;
ans[1] = j;
}
return ans;
}
}
}
return NULL;
}
我是 LeetCode 的新手,我唯一的 C 语言背景是它的一门基础知识。
我想我应该在这个答案中补充一点,LeetCode 可能很有趣,或者你认为它可以帮助您学习一门语言或帮助您在某个地方被录用,但这不是开始一门新语言的正确地方,也没有教你最佳实践。
在我看来,LeetCode 的目标是更深入地了解算法和数据结构,但你需要事先知道你正在使用的语言。如果你只知道一些基础知识,并且为第一个简单的问题而苦苦挣扎,我建议你在尝试解决一些 LeetCode 问题之前,先学习一些关于这门语言的知识。
该函数存在几个问题。
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int *ans;
ans = (int*)malloc(2*sizeof(int));
*returnSize = 2;
for(int i=0; i<numsSize; i++){
for(int j=i++ ; j<numsSize; j++){
if( nums[i] + nums[j] == target ){
ans[0] = i;
ans[1] = j;
break;
}
}
}
return *ans;
}
第一个是表达式具有类型,但返回类型是 。您需要返回一个指针,而不是 类型的对象。*ans
int
int *
int
return ans;
注意表达式等价于表达式。*ans
ans[0]
第二个问题是在内部 for 循环中使用后缀递增运算符。由于这种增量,指针 wll 指向的数组的某些元素将被跳过,因为该变量在外部 for 循环中第二次递增。i++
nums
i
内部 for 循环中使用的语句仅中断内部 for 循环。break
该函数返回指向已分配的动态数组的指针
ans = (int*)malloc(2*sizeof(int));
*returnSize = 2;
但是,如果数组中找不到相等的元素,则函数的调用方将无法确定这一点。target
还要注意的是,教给糟糕的编程风格。至少该函数应声明为LeetCode
size_t * twoSum( const int *nums, size_t numsSize, int target );
第四个参数是冗余的。如果数组中没有两个元素等于 target,则该函数只能返回一个 null 指针。很明显,在没有参数的情况下,由于函数的任务,返回的指针可以指向两个元素的数组。returnSize
函数可以按以下方式定义
size_t * twoSum( const int *nums, size_t numsSize, int target )
{
size_t *ans = NULL;
if ( !( numsSize < 2 ) )
{
int found = 0;
for ( size_t i = 0; !found && i < numsSize; i++ )
{
size_t j = i + 1;
while ( j < numsSize && nums[i] + nums[j] != target ) ++j;
if ( j != numsSize )
{
found = 1;
ans = malloc( 2 * sizeof( *ans ) );
if ( ans != NULL )
{
nums[0] = i;
nums[1] = j;
}
}
}
}
return ans;
}
在调用方中,你可以通过以下方式检查返回的指针是否不等于 NULL
size_t *ans = twoSum( nums, numsSize, target );
if ( ans != NULL )
{
// do something with the returned indices in the dynamically allocated array
}
尽管返回两个成员的结构而不是动态分配的数组会更好。类似的东西
struct Pair
{
size_t first;
size_t second;
};
在这种情况下,该函数可以如下所示
struct Pair twoSum( const int *nums, size_t numsSize, int target )
{
struct Pair ans = { .first = 0, .second = 0 };
if ( !( numsSize < 2 ) )
{
int found = 0;
for ( size_t i = 0; !found && i < numsSize; i++ )
{
size_t j = i + 1;
while ( j < numsSize && nums[i] + nums[j] != target ) ++j;
if ( j != numsSize )
{
found = 1;
ans.first = i;
ans.second = j;
}
}
}
return ans;
}
在来电者中,你可以写
struct Pair ans = twoSum( nums, numsSize, target );
if ( ans.first != ans.second )
{
// do something with the returned indices
}
评论
int*
ans
return ans;
for(int j=i++ ; j<numsSize; j++)
i
for(int j=i+1 ; j<numsSize; j++)
int *
int
return *ans;
return ans;
*ans
int
ans
int *
break
return arr;
return NULL;
target
break;
return ans;
free(ans);
return NULL;