(c99之前不支持在for循环括号中定义变量)
1.爬楼梯 (LeetCode70)
int climbStairs(int n){
if(n<=0) return 0;
if( n== 1) return 1;
if( n== 2) return 2;
int res=0;
int pre=1;
int prePre=2;
int i;
for(i=3; i<=n ;i++){
res=pre+prePre;
pre=prePre;
prePre=res;
}
return res;
}
斐波那契数列中:pre=0,prePre=1
2.移动0 (LeetCode283)
void moveZeroes(int* nums, int numsSize){
if(numsSize==0) return;
int i,j;
for(i=0,j=0;i<numsSize;i++){
if(nums[i]!=0){
nums[j]=nums[i];
j++;
}
}
for(;j<numsSize;j++){
nums[j]=0;
}
}
3.找到所有数组中消失的数字(LeetCode448)
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize){
if(numsSize<=0) return NULL;
int i;
for(i=0;i<numsSize;i++){
int a=(nums[i]-1)%numsSize;
nums[a] +=numsSize;
}
int count=0;
for(i=0;i<numsSize;i++){
if(nums[i]<=numsSize) count++;
}
int * returnNums = (int *)malloc( sizeof(int)*count );
int j=0;
for(i=0;i<numsSize;i++){
if(nums[i]<=numsSize) returnNums[j++]=i+1;
}
*returnSize=count;
return returnNums;
}
4.反转链表(LeetCode206)
(有待改进,1.不用申请新内存结点,2.while循环改进)
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* reverseList(struct ListNode* head){
if( NULL==head ) return NULL;
if( NULL==head->next ) return head;
struct ListNode* res = (struct ListNode*) malloc (sizeof(struct ListNode));
res->next=NULL;
res->val=-1;
struct ListNode* p = head;
struct ListNode* pNext = p->next;
struct ListNode* resNext = res->next;
while(NULL!=p && NULL!=p->next){
p->next=resNext;
res->next=p;
resNext=p;
p=pNext;
pNext=pNext->next;
}
p->next=resNext;
res->next=p;
return res->next;
}
5.合并两个有序链表(LeetCode21)
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL)
return l2;
if(l2==NULL)
return l1;
if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
6.字符串相加(LeetCode415)
char* addStrings(char* num1, char* num2) {
int i = strlen(num1) - 1, j = strlen(num2) - 1, add = 0;
char* ans = (char*)malloc(sizeof(char) * (fmax(i, j) + 3));
int len = 0;
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1[i] - '0' : 0;
int y = j >= 0 ? num2[j] - '0' : 0;
int result = x + y + add;
ans[len++] = '0' + result % 10;
add = result / 10;
i--, j--;
}
// 计算完以后的答案需要翻转过来
for (int i = 0; i < len/2; i++) {
int t = ans[i];
ans[i] = ans[len - i - 1];
ans[len - i - 1] = t;
}
ans[len++] = 0;
return ans;
}
7.快速排序
void quickSort(int *arr, int low, int high){
if (low < high){
int i = low;
int j = high;
int k = arr[low];
while (i < j){
while(i < j && arr[j] >= k) j--; // 从右向左找第一个小于k的数
arr[i] = arr[j]; //此时可能i等于j,因此可能会多执行一步无用的操作
while(i < j && arr[i] < k) i++; // 从左向右找第一个大于等于k的数
arr[j] = arr[i];
}
arr[i] = k;
quickSort(arr, low, i - 1); // 排序k左边
quickSort(arr, i + 1, high); // 排序k右边
}
}
8.二分查找
int binarySearch(int nums[], int size, int target) //nums是数组,size是数组的大小,target是需要查找的值
{
int left = 0;
int right = size - 1; // 定义了target在左闭右闭的区间内,[left, right]
while (left <= right) { //当left == right时,区间[left, right]仍然有效
int middle = left + ((right - left) / 2);//等同于 (left + right) / 2,防止溢出
if (nums[middle] > target) {
right = middle - 1; //target在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; //target在右区间,所以[middle + 1, right]
} else { //既不在左边,也不在右边,那就是找到答案了
return middle;
}
}
//没有找到目标值
return -1;
}
9.两数之和(LeetCode1)
由于不方便使用Map,所以先使用快排对数组排序,再for循环遍历,通过二分法查询对应结果。
时间复杂度O(nlogn),空间复杂度O(n)
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
//复制一个原来的数组,用来排序
int * sortedNums=(int *) malloc( sizeof(int)*numsSize );
int k;
for(k=0;k<numsSize;k++){
sortedNums[k]=nums[k];
}
quickSort(sortedNums,0,numsSize-1);
*returnSize=2;
int * res=(int *) malloc( sizeof(int)*2 );
int i;
for(i=0; i<numsSize; i++){
//遍历原数组nums,在有序的数组sortedNums去查询目标值
int flag=binarySearch(sortedNums,numsSize,target-nums[i]);
if(flag>=0){
int j;
//根据有序的数组sortedNums查询到的值在原数组中找到下标
for(j=0;j<numsSize;j++){
//返回的值不能是相同的元素(下标)
if(sortedNums[flag]==nums[j] && i!=j){
res[0]=i;
res[1]=j;
return res;
}
}
}
}
return NULL;
}
10.图像压缩(MOOC算法设计与分析-屈婉玲 6.2)
1.黑白图像存储
像素点灰度值 : 0∼255,为8位二进制数
图像的灰度值序列 : { p1, p2, … , pn},pi为第i个像素点灰度值
图像存储:每个像素的灰度值占8位,总计空间为 8n
2.图像变位压缩的概念
变位压缩存储: 将{p1, p2,…,pn}分成 m 段
S1, S2, … , Sm
同一段的像素占用位数相同,第 t 段有 l[t]个像素,每个占用 b[t]位
段头:记录l[t]
(8位)和b[t]
(3位)需要11位
总位数为:b[1]⋅l[1]+b[2]⋅l[2]+… +b[m]⋅l[m]+11m
3.图像压缩问题
约束条件:第 t 段像素个数 l[t] ≤256
第 t 段占用空间:b[t]×l[t] + 11
问题 :给定像素序列{ p1, p2, …, pn},
确定最优分段,即
4.实例
灰度值序列:P={10,12,15,255,1,2,1,1,2,2,1,1}
分法1: S1= {10, 12, 15},S2={255}, S3={1, 2, 1, 1, 2, 2, 1, 1}
分法2:S1={10,12,15,255,1,2,1,1,2,2,1,1}
分法3: 分成12组,每组一个数
存储空间:
分法1:11×3+4×3+ 8×1+2×8 = 69
分法2:11×1+8×12 =107
分法3:11×12+4×3+8×1+1×5+2×3=163
#include<iostream>
#include<string>
#define Header 11
#define Lmax 256
#define N 1000
using namespace std;
//全部1序
int p[N+1]; //原序列
int S[N+1]; //前N项最优解
int L[N+1]; //当前分组有几项
int b[N+1]; //每项位数
int FL[N+1]; //有几个分组
//求位数
int length(int p){
int t = 0;
while(p > 0){
t++;
p /= 2;
}
return t;
}
//图像压缩
void compress(int p[], int n){
int bmax = 0;
int S[n+1];
S[0] = 0;
for(int i = 1; i <= n; i++){
b[i] = length(p[i]);
bmax = b[i];
S[i] = S[i-1] + bmax;
L[i] = 1;
for(int j = 2; j <= i && j <= Lmax; j++){
if(bmax < b[i-j+1]){
bmax = b[i-j+1];
}
if(S[i] > S[i-j]+j*bmax){
S[i] = S[i-j]+j*bmax;
L[i] = j;
}
}
S[i] += Header;
}
//
int count = 0;
for(int j = n; j > 0;){
FL[++count] = L[j];
j = j-L[j];
}
for(int i = 1, j = count; i < j; i++, j--){
int k;
k = FL[i];
FL[i] = FL[j];
FL[j] = k;
}
//输出
cout << "最优解" << S[n] << endl;
cout << "分割====" << endl;
int c = 1;
for(int i = 1; i <= count; i++){
for(int j = 1; j <= FL[i]; j++){
cout << p[c++] << " ";
}
cout << ",";
}
}
// 12 10 12 15 255 1 2 1 1 2 2 1 1
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> p[i];
}
compress(p, n);
return 0;
}