c算法题

找出一个字符串中最长重复次数的子字符串,并计算其重复次数。例如:字符串“abc fghi bc kl abcd lkm abcdefg”,并返回“abcd”和2。

由于题目要求寻找至少重复2次的最长的子字符串,重点在于最长的子字符串,而不在于重复的最多次数。因此我们可以从长度最长的字符串入手,计算其重复次数。只要重复达到2次,即可返回该字符串。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int find_longest_dup_str(char* src, char* dest);
int str_sub(char* src, char* sub, int pos,int len);
int str_cnt(char* src,char* sub);

int main(int argc, char* argv[])
{
    char str[] = "abc fghi bc kl abcd lkm abcdefg";
    char sub[128] = "";
    int cnt;
    cnt = find_longest_dup_str(str,sub);
    printf("result: %s\ncnt: %d \n",sub,cnt);
}

int find_longest_dup_str(char* src, char* dest)
{
    int len;
    int index;
    int cnt;
    for(len = strlen(src);len > 0;len--)
    {
        for(index = 0; index + len-1 < strlen(src); index++)
        {
            str_sub(src,dest,index,len);
            if((cnt = str_cnt(src,dest)) >= 2)
            {
                return cnt;
            }
        }
    }
    return 0;
}

int str_sub(char* src, char* sub, int pos,int len)
{
    int index;
    for(index = 0; index < len;index++)
    {
        sub[index] = src[pos + index];
    }
    sub[index] = ‘\0‘;
}

int str_cnt(char* src,char* sub)
{
    int cnt = 0;
    char tmp[128];
    int index;
    int index_sub;
    for(index = 0;index + strlen(sub)-1 < strlen(src);index++)
    {
        /* method1
        for(index_sub = 0; index_sub < strlen(sub);index_sub++)
        {
            if(src[index + index_sub] != sub[index_sub])
            {
                break;
            }
        }
        if(index_sub == strlen(sub))
        {
            cnt++;
        }
        */
        /* method2
        str_sub(src,tmp,index,strlen(sub));
        if(strcmp(sub,tmp) == 0)
        {
            cnt++;
        }
        */
        // method3
        if(strncmp(src + index,sub,strlen(sub))== 0)
        {
            cnt++;
        }
    }
    return cnt;
}

自然数采用蛇形排列方式填充到数组中。将自然数1、2、3…、N*N逐个顺序插入方阵中适当的位置,这个过程沿斜列进行。将斜列编号为0、1、2…、2n(以i标记,n=N-1),如下面的数据排列,这个排列为蛇形排列。

1   3    4    10

2   5    9    11

6   8   12   15

7  13  14   16

(0,0)                                     和为0

(1,0) (0,1)                             和为1

(0,2) (1,1) (2,0)                     和为2

(3,0) (2,1) (1,2) (0,3)             和为3

(1,3) (2,2) (3,1)                     和为4      --> (0,4) (1,3) (2,2) (3,1) (4,0)

(3,2) (2,3)                             和为5      --> (5,0) (4,1) (3,2) (2,3) (1,4)

(3,3)                                     和为6      --> (0,6) (1,5) (2,4) (3,3) (4,2) (5,1) (6,0)

不难发现只要在同一斜行上的数字,其对应数组行列下标之和总是相等的。

注意,当和为4或者大于4时,填充数字时要注意越界问题,因此我在程序中特意写了一个宏来判断。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 4
#define IS_LEGAL(row,col) ((row) >= 0 && (row) < N && (col) >= 0 && (col) < N )

void print(int (*arr)[N]);
void fill(int (*arr)[N]);

int main(int argc, char *argv[])
{
    int arr[N][N];
    memset(arr,0,sizeof(arr));
    fill(arr);
    print(arr);
    return 0;
}

void print(int (*arr)[N])
{
    int i,j;
    for(i = 0; i < N; i++)
    {
        for(j = 0; j < N; j++)
        {
            printf("%3d",arr[i][j]);
        }
        printf("\n");
    }
}

void fill(int (*arr)[N])
{
    int sum;
    int row,col;
    int num = 0;
    for(sum = 0; sum < 2 * N - 1; sum++)
    {
        if(sum % 2 == 0)
        {
            for(row = 0; row < N; row++)
            {
                col = sum - row;
                if(IS_LEGAL(row,col))
                {
                    arr[row][col] = ++num;
                }
            }

        }else
        {
            for(row = sum; row >=0; row--)
            {
                col = sum - row;
                if(IS_LEGAL(row,col))
                {
                    arr[row][col] = ++num;
                }
            }

        }
    }
}

打印魔方阵,魔方阵是指这样的方针,每一行、每一列以及对角线的和相等。例如三阶魔方阵:

8 1 6

3 5 7

4 9 2

编程打印奇数阶魔方阵。

提示

问题解决的关键是元素的填充,第一个元素1的位置在第一行正中,新的位置应该处于最近插入元素的右上方;但如果右上方的位置超出方针上边界,则新的位置应该取列的最下一个位置;超出右边界则取行的最左的一个位置;若最近插入的元素为n的整数倍,则选下面一行同列上的位置为新的位置。

实现代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int size;
    int row,col;
    int num = 0;
    int index;
    size = atoi(argv[1]);
    /* 动态分配二维数组,用于存放魔方阵 */
    int **arr = (int**)calloc(size,sizeof(int*));
    for(index = 0; index < size; index++)
    {
        arr[index] = (int*)calloc(size,sizeof(int));
    }
    /* 存放魔方阵 */
    row = 0;
    col = size >> 1;
    arr[row][col] = ++num;
    while(num < size * size)
    {
        if(num % size == 0)
        {
            row = (row + 1) % size;
            col = col;
            arr[row][col] = ++num;
        }else
        {
            row = (row - 1 + size) % size;
            col = (col + 1) % size;
            arr[row][col] = ++num;
        }
    }
    /* 打印 */
    for(row = 0; row < size; row++)
    {
        for(col = 0; col < size; col++)
        {
            printf("%-3d",arr[row][col]);
        }
        printf("\n");
    }
    /* 释放存储空间 */
    for(index = 0; index < size; index++)
    {
        free(arr[index]);
        arr[index] = NULL;
    }
    free(arr);
    arr = NULL;

    return 0;
}
时间: 2024-10-09 23:45:34

c算法题的相关文章

笔试算法题(09):查找指定和值的两个数 &amp; 构造BST镜像树

出题:输入一个已经升序排序的数组和一个数字:要求在数组中查找两个数,这两个数的和正好等于输入的那个数字,输出任意一对数字就可以,要求时间复杂度是O(n): 分析:对于升序排序的数组{-i-j-k-m--},只有可能是i+m=j+k(j和k可能是同一个数),所以可以从两边往中间收缩而忽视其他交叉相加的情况: 解题: 1 void FindSumFactor(int *array, int length, int sum) { 2 int left=0, right=length-1; 3 whil

笔试算法题(08):输出倒数第K个节点

出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: 1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* FindLastKth(Node *head, int k) { 6 if(head==NULL) { 7 printf("\nhead is NULL\n"); 8 exit(0); 9 } 10 Nod

笔试算法题(07):还原后序遍历数组 &amp; 半翻转英文句段

出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历): 分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树): 解题: 1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 ==

java基础算法题

为了提高自己的代码能力和算法能力,我决定每天学习一道算法题,吸收前辈思想. [程序1] TestRabbit.java 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子数量的规律为数列:1,1,2,3,5,8,13.....其实就是斐波那契数列  使用递归就可以实现 1 /** 2 * 兔子问题 3 * 2016/5/9 4 * 斐波那契数列求值 5 *题目:古典问题:有一对兔子,

ios 算法题

1兔子算法题 兔子可以跳一步2步或者3步,问跳到100有多少种跳法? // 兔子可以跳一步2步或者3步 // 问跳到100有几种跳法 /* 分析1 两个变量,X*2+Y*3=100. X最大为50,X最小为2 Y最大为32.最小为0 分析2 某个情景分析:假设X=35,Y为10时, 虽然知道了数量,但是兔子的35小步,和10大步的顺序是怎样的? 应为组合-> 45个节点中,选择10个放三步的.那就是简单的C(45 10).变成阶乘,就解得出来. */ double temp=0.0f; for

[solution]腾讯TEG_计算广告组_算法题

度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的一个无序的数组a[1..N],请将a进行排序,要求所有正数都排在0之前,所有负数都排在0之后(如果没有0,则所有正数排在负数前) 要求时间复杂度O(N),空间复杂度O(1) 题目不难,但给思考的时间很短,大约不到5分钟吧.当时脑子比较短路,于是只给出了O(n) O(n)复杂度的算法,然后就被面试官挂

算法题——翻转链表中的一段

题目:给出一个链表中的两个指针p1和p2,将其之间的结点翻转. 思路:可以通过交换结点内的值来实现结点的翻转,空间为O(N):如果要求不能交换值,那么仅凭p1和p2是无法翻转的,只能交换两个指针之间的链表. 代码: 交换值: 1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 }; 6 7 void reverseNodes(ListNode *p1, ListNode *p2) { 8 if ( p1 == NULL || p2 == NU

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

一天一道算法题--6.25--无定义

感谢微信平台---一天一道算法题--每天多一点进步---- 其实今天我接下去补上的几题都来自---待字闺中 所以我就原封不动的将它的题目与分析搬过来了 原题 给定一个数组,我们可以找到两个不相交的.并且是连续的子数组A和B,A中的数字和为sum(A), B中的元素和为sum(B).找到这样的A和B,满足sum(A) - sum(B)的绝对值是最大的. 例如:[2, -1 -2, 1, -4, 2, 8]划分为A=[-1, -2, 1, -4], B=[2, 8], 最大的值为16 分析 如果没有