Question 1: Given an array, please get the length of the longest arithmetic sequence. The element order in the arithmetic sequence should be same as the element order in the array. For example, in the array {1, 6, 3, 5, 9, 7}, the longest arithmetic sequence is 1, 3, 5, and 7, whose elements have same order as they are in the array, and the length is 4.
参考: http://codercareer.blogspot.com/2014/03/no-53-longest-arithmetic-sequence.html
最妙的是如何计算等差数列长度。请看参考链接,确实是很妙啊!
/* Copyleft: Ming Lin <minggr@gmail.com> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct pair {
int diff;
int i, j;
struct pair *next;
};
struct pair_list {
int diff;
struct pair *head;
struct pair *tail;
struct pair_list *chain;
};
struct hash {
struct pair_list **head;
int size;
};
struct hash *init_hash(int n)
{
struct hash *h;
struct pair_list **p;
int size;
h = malloc(sizeof(*h));
size = n*sizeof(struct pair_list *);
p = malloc(size);
memset(p, 0, size);
h->head = p;
h->size = n;
return h;
}
int hash_index(struct hash *h, int key)
{
if (key < 0)
key = -key;
return key % h->size;
}
int mycount = 0;
void pair_add(struct pair_list **head, struct pair *p)
{
struct pair_list *pl, *prev_pl;
if (!*head) {
pl = malloc(sizeof(struct pair_list));
pl->diff = p->diff;
pl->head = pl->tail = p;
pl->chain = NULL;
*head = pl;
return;
}
pl = prev_pl = *head;
while (pl && pl->diff != p->diff) {
prev_pl = pl;
pl = pl->chain;
}
if (pl) {
pl->tail->next = p;
pl->tail = p;
} else {
pl = malloc(sizeof(struct pair_list));
pl->diff = p->diff;
pl->head = pl->tail = p;
pl->chain = NULL;
prev_pl->chain = pl;
}
}
void hash_add_pair(struct hash *h, struct pair *p) {
int i;
i = hash_index(h, p->diff);
mycount++;
pair_add(&h->head[i], p);
}
void hash_add(struct hash *h, int diff, int i, int j)
{
struct pair *p;
p = malloc(sizeof(struct pair));
p->diff = diff;
p->i = i;
p->j = j;
p->next = NULL;
hash_add_pair(h, p);
}
void hash_build(struct hash *h, int data[], int n)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
hash_add(h, data[j]-data[i], i, j);
}
}
}
void pair_list_dump_one(int *data, struct pair_list *pl)
{
struct pair *p;
p = pl->head;
printf(" diff %d: ", pl->diff);
while (p) {
printf("{%d,%d -> %d,%d} ", p->i, p->j, data[p->i], data[p->j]);
p = p->next;
}
printf("\n");
}
void pair_list_dump(int *data, struct pair_list *pl)
{
while (pl) {
pair_list_dump_one(data, pl);
pl = pl->chain;
}
}
void hash_dump(struct hash *h, int *data)
{
int i;
for (i = 0; i < h->size; i++) {
printf("index %d\n", i);
pair_list_dump(data, h->head[i]);
}
}
int pair_list_len_one(struct pair_list *pl, int *len, int n)
{
struct pair *p;
int max = 0;
while (n >= 1) {
n--;
len[n] = 1;
}
p = pl->head;
while (p) {
len[p->j] = len[p->i] + 1;
if (len[p->j] > max)
max = len[p->j];
p = p->next;
}
return max;
}
int pair_list_len(struct pair_list *pl, int *len, int n)
{
int max = 0;
while (pl) {
int tmp = pair_list_len_one(pl, len, n);
if (tmp > max)
max = tmp;
pl = pl->chain;
}
return max;
}
int length_of_longest_arithmetic_sequence(struct hash *h)
{
int *len;
int max = 0;
int i;
len = malloc(h->size * sizeof(int));
for (i = 0; i < h->size; i++) {
int tmp = 0;
if (h->head[i])
tmp = pair_list_len(h->head[i], len, h->size);
if (tmp > max)
max = tmp;
}
return max;
}
int main()
{
struct hash *h;
//int data[] = {1, 6, 3, 5, 9, 7};
//int n = 6;
int data[] = { 1, 8, 3, 6, 5, 4, 7, 2, 9 };
int n = 9;
h = init_hash(n);
hash_build(h, data, n);
hash_dump(h, data);
printf("length_of_longest_arithmetic_sequence=%d\n", length_of_longest_arithmetic_sequence(h));
return 0;
}