[英]question about two sum leetcode problem: brute force approach in C
我不明白這段代碼中采取的一些小動作,例如
i) 為什么我們需要做 &rs,為什么我們不能寫
int returnSize;
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, int*returnSize);
if(returnSize == 0)
而不是&rs...
這樣做有什么問題? 我在這里運行代碼:#include <stdio.h> #include <stdlib.h>
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int i, j;
int* ret_arr = (int*)malloc(2*sizeof(int));
if(ret_arr == NULL){
// *returnSize = 0;
returnSize = 0;
return NULL;
}
for(i = 0; i< numsSize; i++){
for(j = i+1; j< numsSize; j++){
if(nums[i] + nums[j] == target){
//*returnSize = 2;
returnSize = 2;
ret_arr[0] = I;
ret_arr[1] = j;
return ret_arr;
}
}
}
//*returnSize = 0;
returnSize = 0;
free(ret_arr);
return NULL;
}
int main()
{
int a[] = {2,7,11,15};
int returnSize, target = 18;
int *p = NULL;
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, int*returnSize);
//if(*returnSize == 0){
if(returnSize == 0){
printf("target not found");
}else{
printf("target found at indices %d and %d/n", p[0], p[1]);
free(p);
}
return 0;
}
error result:
main.c: In function ‘twoSum’:
main.c:34:28: warning: assignment to ‘int *’ from ‘int’ makes
pointer from integer without a cast [-Wint-conversion]
34 | returnSize = 2;
| ^
main.c: In function ‘main’:
main.c:57:48: error: expected expression before ‘int’
57 | p = twoSum(a, sizeof(a)/sizeof(a[0]), target,
int*returnSize);
| ^~~
完整代碼: https://onlinegdb.com/7OpTpwxZy3
我不知道這對編譯器沒有意義。
ii) 指針數組概念 Q
我們需要在第 60 行聲明指針p
,因為要訪問返回的數組元素(兩個 sum 函數的)並將它們打印出來(就像它們在行中使用的那樣),從 main 屏幕上。 問題:當我們已經在 MAIN 中聲明了指針 p 時,為什么我們需要兩個和 FUNCTION 的指針,它就像指針指向一個指針(如int*a, int*p, p = a
),為什么代碼可以工作?
如果我在雙數 function 前面刪除第 4 行(第 2 張圖片)中的“int*”,則會出現錯誤。main.c:28:1: 警告:返回類型默認為“int”[-Wimplicit-int] 28 | twoSum(int* nums, int numsSize, int target, int* returnSize){ | ^~~~~~ main.c:在 function 'twoSum' 中:main.c:34:16:警告:從返回類型為 'int' 的 function 返回 'void *' 使 integer 從沒有強制轉換的指針 [-Wint -轉換] 34 | 返回 NULL; | ^~~~ main.c:43:24:警告:從返回類型為“int”的 function 返回“int *”使得 integer 從沒有強制轉換的指針 [-Wint-conversion] 43 | 返回 ret_arr; | ^~~~~~~ main.c:49:12: 警告:從返回類型為“int”的 function 返回“void *”使得 integer 來自沒有強制轉換的指針 [- Wint-conversion] 49 | 返回 NULL; | ^~~~ main.c: In function 'main': main.c:60:4: warning: assignment to 'int *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 60 | p = twoSum(a, sizeof(a)/sizeof(a[0]), target, &rs); | ^
這是完整的參考代碼:#include <stdio.h> #include <stdlib.h>
twoSum(int* nums, int numsSize, int target, int* returnSize){
int i, j;
int* ret_arr = (int*)malloc(2*sizeof(int));
if(ret_arr == NULL){
*returnSize = 0;
return NULL;
}
for(i = 0; i< numsSize; i++){
for(j = i+1; j< numsSize; j++){
if(nums[i] + nums[j] == target){
*returnSize = 2;
ret_arr[0] = I;
ret_arr[1] = j;
return ret_arr;
}
}
}
*returnSize = 0;
free(ret_arr);
return NULL;
}
int main()
{
int a[] = {2,7,11,15};
int rs, target = 18;
int *p = NULL;
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, &rs);
if(rs == 0){
printf("target not found");
}else{
printf("target found at indices %d and %d/n", p[0], p[1]);
free(p);
}
return 0;
}
我希望我提供了足夠的信息來理解這個問題,對於有經驗的程序員來說,問題可能相當簡單,但我只是一個初學者。 如果您認為自己是在向初學者解釋,也請用簡單易懂的詞來解釋。
將圖像寫成文本:我不確定該怎么做,因為在這種情況下,圖像似乎比文本更容易。
i) 我嘗試更改主 function 以及 twosum function 中的代碼,如下所示。
int returnSize;
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, int*returnSize);
if(returnSize == 0)
ii) 我嘗試在第 4 行(第 2 張照片)中刪除int*
,在 twosum function 前面,但我在此處顯示錯誤:
似乎對什么是指針、它們如何工作以及為什么在已發布的程序中使用指針存在基本的誤解。
function twoSum
試圖找到數組中兩個元素的總和等於給定目標。 這段代碼的作者做出了以下設計選擇:
// The function returns a POINTER to some memory, allocated in the free store,
// where the two indeces will be stored, or NULL if no elements satisfy the constraint.
int*
twoSum( int* nums, int numsSize // The array is passed as pointer to its first
// element and size (number of elements)
, int target
, int* returnSize ) // This POINTER is used to "return" the size
// of the memory allocated in this function
// to the caller. This may be referred to as
// an "out parameter", it allows the function
// to change the value of a variable stored elsewhere.
{
int i, j;
int* ret_arr = (int*)malloc(2*sizeof(int));
if(ret_arr == NULL){
*returnSize = 0;
// ^ The pointer must be DEREFERENCED to access the value of the pointee.
return NULL;
}
/* [...] */
}
int main()
{
int a[] = {2,7,11,15};
int returnSize, target = 18;
//^^^^^^^^^^^^ This variable is declared as an int.
int *p = NULL;
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, &returnSize);
// We need to pass its ADDRESS here ^^^^^^^^^^^
// because this function is expecting a POINTER to int.
if( returnSize == 0){
// ^^^^^^^^^^ Beeing an int, it must be used as an int value.
printf("target not found");
} else {
printf("target found at indices %d and %d/n", p[0], p[1]);
free(p); // <- Correct. The caller has this responsability.
}
return 0;
}
要回答第一點,它需要&
因為它需要將在main
中聲明的變量returnSize
的地址作為int
。 該地址被傳遞給 function,用於初始化局部變量returnSize
,該變量在 function 的簽名中聲明為int *
類型的參數,一個指針。 請注意,這是兩個不同的對象,在不同的范圍內,具有不同的生命周期和不同的類型。
電話不能寫成
p = twoSum(a, sizeof(a)/sizeof(a[0]), target, int*returnSize);
// ^^^^ Syntax error, this isn't a declaration
當我們已經在
main
中聲明了指針p
時,為什么我們需要twoSum
function 的指針?
我不確定 OP 的疑慮是什么。 main
中聲明的變量需要賦一個有意義的值,所以它使用function返回的值。在twoSum
內部,需要一個指針類型的變量來分配所需的memory並返回給main
。
這不是完成此任務的唯一方法,事實上,我們可能更願意不在 function 中分配任何內存,而是傳遞一個地址:
#include <stdio.h>
#include <stdlib.h>
// If there exist two elements whose sum equals the 'target', the function returns 1
// and the indices of these elements are stored in the array 'indices'.
// Otherwise, the function returns 0 and doesn't modify 'indices'.
int
find_indices_of_sum( size_t n, int const* arr
, int target
, int *indices )
{
for(size_t i = 0; i < n; ++i)
{
for(size_t j = i + 1; j < n; ++j)
{
if( arr[i] + arr[j] == target )
{
indices[0] = i;
indices[1] = j;
return 1;
}
}
}
return 0;
}
int main(void)
{
int a[] = {2, 7, 11, 15};
size_t a_size = sizeof a / sizeof *a;
int target = 18;
// Declares the array in main.
int indices[2];
if ( find_indices_of_sum(a_size, a, target, indices) )
{ // Pass the address of its first element ^^^^^^^, the size is known (2).
printf("Target found at indices %d and %d\n", indices[0], indices[1]);
// ^^
// No need to free anything. 'indices' has automatic storage duration.
}
else
{
puts("Target not found");
}
return 0;
}
我們還可以直接從struct
返回一個包含所有需要的信息的結構,而不使用任何“輸出參數”。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct idx_pair
{
size_t first, second;
};
static inline bool is_valid(struct idx_pair p)
{
return p.first != p.second;
}
// The function returns both the indices wrapped in a single struct.
struct idx_pair
find_inidces_of_sum( size_t n, int const *arr
, int target )
{
for(size_t i = 0; i < n; ++i)
{
for( size_t j = i + 1; j < n; ++j)
{
if( arr[i] + arr[j] == target )
{
return (struct idx_pair){ .first = i, .second = j };
// ^^^^^^^^^^^^^^^^^ This is not a cast, it's a
// compound literal with designated initializers.
}
}
}
return (struct idx_pair){ .first = 0, .second = 0 };
}
int main(void)
{
int a[] = {2, 7, 11, 15};
size_t a_size = sizeof a / sizeof *a;
int target = 18;
struct idx_pair solution = find_indices_of_sum(a_size, a, target);
if ( is_valid(solution) )
{
printf("Target found at indices %d and %d\n", solution.first, solution.second);
}
else
{
puts("Target not found");
}
return 0;
}
但請注意,您的編譯器可能無法優化所有副本,即使涉及的結構不是那么大,生成的程序集在某些硬件上也可能不是最佳的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.