数据结构回顾复习总结(一)(时间复杂度、空间复杂度)

一 复杂度::

  学习数据结构的意义在于可以使我们写的程序更加的高效率,而在写程序的时候离不开复杂度的考虑,下面先从2个循环小题目开始 了解为什么要考虑复杂度的概念。

例题1,给定n个元素 求其中奇数的个数

这个题目比较简单 我就这就给出代码了 其主要思想就是我们可以遍历n个元素的数组a 然后依次的辨别他们

int count(int n,int a[])
{
   int Count=0;
for(size_t i=0;i<n;i++)
{
//依次判断每次元素是否符合题目要求 提示:判断奇数的方法可以用 %2(模2看余数是否是1 )也可以用&运算符 &1看是结果是否是1  这里%2大家经常用到 我就给&的方法了
  if(a[i]&1)
{
Count++;
}

}
return Count;

}

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)

 这是测试结果 第一个题目很简单 接着我们给第二个题目,

题目二 给定n个元素的数组a,求有多少组三元组,满足a(i)+a(j)+a(k) 是奇数

这个相比较上面那个会相对于复杂一点点 也可以用嵌套循环的方式来解决 也可以用递归的方式来解决这个问题,注意代码的i j k的取值范围。 

int countThree(int n, int start,int a[])
{
	int count = 0;
	for (size_t i = start; i < n; i++)
	{
		for (size_t j = i+1; j < n; j++)
		{
			for (size_t k = j+1; k < n; k++)
			{

				if ((a[i] + a[j] + a[k]) & 1)
				{
					count++;
					cout << a[i]<<"   " << a[j] << "  " << a[k] << endl;
				}

			}
		}


	}
	return count;

}

    上述代码虽然可以实验 但是套了三层循环了 还有一种方法可以使得代码量减小 那就是采用递归的方法,递归的方法更加的简洁高效 递归代码如下所示:

int countthree(int n, int a[], int start, int k, int sum)
{
	if (k == 0)
	{
		return (sum & 1) ? 1 : 0; //运算符顺序的关系 记得打();

	}
	int p = 0;
	for (size_t i = start; i < n; i++)
	{
		p += countthree(n, a, i+ 1, k - 1, sum + a[i]);
	}


	return p;
}

第二种的递归实现的代码课程稍微有一点难度我解释一下,参数部分分别是 元素个数 数组a  开始start,k就是你要搞几元的,sum就是为了算和用的 记得初始传参要传0;这是我程序中我自己传参的 可以拷贝我的跑一下。

	int a[5] = { 0,1,2,3,4 };
	
	int b = countthree(5, a,0,3,0);
	int c = countThree(5, 0, a);

当然了如果你要计算偶数改一下三目运算符就可以了 如下::

int countthree(int n, int a[], int start, int k, int sum)
{
	if (k == 0)
	{
		return (sum & 1) ? 0 : 1; //运算符顺序的关系 记得打(); 这个是计算偶数的哈 不要跟计算奇数的弄混了

	}
	int p = 0;
	for (size_t i = start; i < n; i++)
	{
		p += countthree(n, a, start + 1, k - 1, sum + a[i]);
	}


	return p;
}

想必到这里关于复杂度的概念你就有一定的意识了 接着我们继续讨论:时间复杂度

时间复杂度定义::算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度

简言之我们用一个表示法 称为大O表示法来表示::

O(n)表示我们写的算法是线性 就是刚才的遍历一次数组就是线性的

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)表示我们写的算法是平方级别的复杂度 这个大家可以写一个双层循环比如给你一个素组我要求二元的 两个数的加和 是奇数  上面我给了三元的了 我就不写二元的了 大家可以自己写一下。

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)    这个就是我 们写的那个三层循环立方级别的时间复杂度。

二分查找算法的时间复杂度是对数阶的 数据结构回顾复习总结(一)(时间复杂度、空间复杂度)写一个二分查找的例题吧:

题目3 给定一个有序数组a,查找数组里面的元素b,要求返回数组b的下标
int getmidvalue(int n, int b,int a[])
{
	int end = n - 1;
	int begin = 0;
	while (begin <= end)
	{
		int mid = (begin + end) >> 1;
		if (a[mid] > b)
		{
			end = mid-1;
		}
		else if (a[mid] < b)
		{
			begin= mid+1;
		}
		else if (a[mid] == b)
		{
			return mid;
		}
	}

	return -1;
}

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)判断素数就是根号阶的问题 


bool is(int n)
{
	if (n == 1)
	{
		return false;

	}
	int b = sqrt(n + 0.0);
	for (size_t i = 2; i < b; i++)
	{
		if (n % i == 0)
		{
			return false;
		}
	}

	return true;

}

空间复杂度::

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)

 接下来每日两个oj题目来学习c

(1)

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)

189. 轮转数组 - 力扣(LeetCode) (leetcode-cn.com)//leetcode 连接

void reveserfun(int* arr,int start,int final)
{
    while(start<final)
    {
     int tmp=arr[start];
     arr[start]=arr[final];
     arr[final]=tmp;
     start++;
     final--;
    }

}
void rotate(int* nums, int numsSize, int k){

 k = k % numsSize;
reveserfun(nums,numsSize-k,numsSize-1);
reveserfun(nums,0,numsSize-1-k);
reveserfun(nums,0,numsSize-1);
int i=0;
for(i=0;i<numsSize-1;i++)
{

    printf("%d,",nums[i]);
}
printf("\n");

}

 这个题目是有多种方法的 比如简单的可以一个一个转换

(2)

数据结构回顾复习总结(一)(时间复杂度、空间复杂度)

这个题的思想及其简单就是再定义一个数组 用定义的减去之前数组的和就可以

int missingNumber(int* nums, int numsSize)
{

 int b[numsSize+1];
 for(size_t i=0;i<=numsSize;i++)
 {
     b[i]=i;
 }
 int c=0;
for(size_t j=0;j<=numsSize;j++)
{
    c+=b[j];
}
int d=0;
for(size_t j=0;j<numsSize;j++)
{
    d+=nums[j];
}

return c-d;
}

 

上一篇:Foundation框架中的NSFileManager二


下一篇:iOS开发 解决NSLog打印不全以及打印中文乱码的问题