Back home

ARTES #007

ARTES #007

ARTES es una actividad iniciada por 由左耳朵耗子--陈皓: Haga al menos una pregunta sobre el algoritmo leetcode cada semana, lea y comente al menos un artículo técnico en inglés, aprenda al menos una habilidad técnica y comparta un artículo con opiniones y pensamientos. (Es decir, Algoritmo, Revisión, Sugerencia y Compartir se denominan ARTS) y persisten durante al menos un año.

##ARTES 007

Este es el séptimo artículo. Solía ​​​​ser confundido al mirar algoritmos, pero ahora poco a poco me estoy familiarizando y tengo ideas. Espero que mejore cada vez más en el futuro.

Pregunta sobre el algoritmo del algoritmo

Algoritmo leetcode pregunta 15 3Sum: Dificultad: Moderada

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

El primer método que me viene a la mente es el siguiente, que por supuesto es el menos eficiente. En mi dispositivo, se necesitan 15 segundos para probar 3000 datos.


int** threeSum(int* nums, int numsSize, int* returnSize) {
    int **a= NULL;  //用二级指针动态申请二维数组
    int count = 0;
    for (int i =0; i < numsSize-2; i++) {
        for (int j =i+1; j < numsSize-1; j++) {
            for (int k  =j+1; k<numsSize; k++) {
                int first = nums[i];
                int second = nums[j];
                int third = nums[k];
                if (first + second + third == 0) {
                    if (first < second ) {
                        int temp =first;
                        first = second;
                        second = temp;
                    }
                    
                    if (first < third ) {
                        int temp =first;
                        first = third;
                        third = temp;
                    }
                    
                    if (second<third) {
                        int temp =second;
                        second = third;
                        third = temp;
                    }
                    
                    
                    int b = 0;
                    if(a != NULL){
                        for (int loop = 0; loop < count; loop++) {
                            int *aa = a[loop];
                            
                            if (aa[0] == first && aa[1] == second) {
                                //已经存在
                                b = 1;
                                break;
                            }
                            
                        }
                    }
                    
                    if (b == 0) {
                        int* result = (int*)malloc(sizeof(int) * (3));
                        result[0] = first;
                        result[1] = second;
                        result[2] = third;
                        
                        if (count ==0) {
                            count++;
                            a=(int**)malloc(sizeof(result)*count);
                        }
                        else{
                             count++;
                             a=(int**)realloc(a,sizeof(int*)*count);
                        }
                        
                        a[count-1] = result;
                    }
                }
            }
        }
    }
    *returnSize = count;
    return a;
}

Al observar las indicaciones, todas se clasifican primero. Después de ordenar, pensé en la búsqueda binaria, así que la implementé de la siguiente manera

/插入排序
int* insertionSort(int nums[],int numsSize) {
    for (int j = 1; j < numsSize; j++) {
        int  sortingNum = nums[j];
        for (int i = j-1; i >=0; i--) {
            if (sortingNum < nums[i] ) {
                int temp = nums[i+1];
                nums[i+1] = nums[i];
                nums[i] = temp;
            }
        }
    }
    return nums;
}


// 二分查找
int binary_search(int arr[],int left,int right,int element){
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid]>element){
            right = mid - 1;
        }
        else if(arr[mid]<element){
            left = mid + 1;
        }
        else{
            return mid;
        }
    }
    return -1;
}

int** threeSum3(int* nums1, int numsSize, int* returnSize) {
    int *dddsd = insertionSort(nums1,numsSize);
    if(dddsd[0] > 0)
        return NULL;
    if(dddsd[numsSize-1] < 0)
        return NULL;
    int **result= NULL;  //用二级指针动态申请二维数组
    int count = 0;
    for (int i =0; i < numsSize-2 && dddsd[i] <=0; i++) {
        for (int j =numsSize-1; j >i && dddsd[j] >= 0; j--) {
            int first = dddsd[i];
            int second = dddsd[j];
            int third = 0 - first - second;
            int dfsd =binary_search(dddsd, i+1, j-1, third);
            if (dfsd == -1) {
                continue;
            }
            third = dddsd[dfsd];
        
            int b = 0;
            if(result != NULL){
                for (int loop = 0; loop < count; loop++) {
                    int *aa = result[loop];
                    
                    if (aa[0] == first && aa[1] == second) {
                        //已经存在
                        b = 1;
                        break;
                    }
                    
                }
            }
        
            if (b == 0) {
                int* sums = (int*)malloc(sizeof(int) * (3));
                sums[0] = first;
                sums[1] = second;
                sums[2] = third;
                
                if (count ==0) {
                    count++;
                    result=(int**)malloc(sizeof(sums)*count);
                }
                else{
                    count++;
                    result=(int**)realloc(result,sizeof(int*)*count);
                }
                
                result[count-1] = sums;
            }
        }
    }
    *returnSize = count;
    return result;
}

El algoritmo anterior, para evitar duplicaciones, lo comparará con el anterior cada vez que se agregue el resultado. De hecho, esta operación se puede optimizar y la implementación final es la siguiente:

//插入排序
int* insertionSort(int nums[],int numsSize) {
    for (int j = 1; j < numsSize; j++) {
        int  sortingNum = nums[j];
        for (int i = j-1; i >=0; i--) {
            if (sortingNum < nums[i] ) {
                int temp = nums[i+1];
                nums[i+1] = nums[i];
                nums[i] = temp;
            }
        }
    }
    return nums;
}


// 二分查找
int binary_search(int arr[],int left,int right,int element){
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid]>element){
            right = mid - 1;
        }
        else if(arr[mid]<element){
            left = mid + 1;
        }
        else{
            return mid;
        }
    }
    return -1;
}

int** threeSum(int* nums, int numsSize, int* returnSize) {
    int *sortedNums = insertionSort(nums,numsSize);
    if(sortedNums[0] > 0)
        return NULL;
    if(sortedNums[numsSize-1] < 0)
        return NULL;
    
    int **result= NULL;  //用二级指针动态申请二维数组
    int count = 0;
    for (int i =0; i < numsSize-2 && sortedNums[i] <=0; i++) {
        if (i > 0 && sortedNums[i] == sortedNums[i-1]) {
            continue;
        }
        for (int j =numsSize-1; j >i && sortedNums[j] >= 0; j--) {
            if (j < numsSize-1 && sortedNums[j] == sortedNums[j+1]) {
                continue;
            }
            
            int first = sortedNums[i];
            int second = sortedNums[j];
            int third = 0 - first - second;
            int dfsd =binary_search(sortedNums, i+1, j-1, third);
            if (dfsd == -1) {
                continue;
            }
            third = sortedNums[dfsd];
        

            int* sums = (int*)malloc(sizeof(int) * (3));
            sums[0] = first;
            sums[1] = second;
            sums[2] = third;
        
            if (count ==0) {
                count++;
                result=(int**)malloc(sizeof(sums)*count);
            }
            else{
                count++;
                result=(int**)realloc(result,sizeof(int*)*count);
            }
            result[count-1] = sums;
        }
    }
    *returnSize = count;
    return result;
}

Revisión

Entra con el programa ¿QUIERES un trabajo en una multinacional exitosa? Te enfrentarás a mucha competencia. Hace dos años, Goldman Sachs recibió un cuarto de millón de solicitudes de estudiantes y graduados. Éstas no son sólo probabilidades desalentadoras para quienes buscan empleo; son un problema práctico para las empresas. Si un equipo de cinco empleados de recursos humanos de Goldman, que trabajan 12 horas todos los días, incluidos los fines de semana, dedicaran cinco minutos a cada solicitud, les tomaría casi un año completar la tarea de examinar la pila.

¿Busca un puesto en una empresa multinacional de éxito? Entonces tienes que enfrentarte a mucha competencia. Hace dos años, Goldman Sachs recibió 250.000 solicitudes de empleo de estudiantes y graduados. Esto no sólo hace que quienes buscan empleo tengan pocas posibilidades de éxito, sino que también trae verdaderos problemas a la empresa. Suponiendo que un equipo de cinco empleados del departamento de recursos humanos de Goldman Sachs trabajara 12 horas al día, las 24 horas del día, y dedicara cinco minutos a cada solicitud, se necesitaría casi un año para examinar esta montaña de solicitudes.

No es de extrañar que la mayoría de las grandes empresas utilicen un programa o algoritmo informático cuando se trata de seleccionar candidatos que buscan puestos junior. Y eso significa que los solicitantes se beneficiarían al saber exactamente qué buscan los algoritmos.

No es de extrañar que la mayoría de las grandes empresas utilicen un programa informático, conocido como algoritmo, para seleccionar candidatos para puestos de nivel inferior. Esto significa que quienes buscan empleo pueden beneficiarse al saber exactamente qué busca el algoritmo.

Victoria McLean es una ex cazatalentos bancarios y gerente de reclutamiento que creó una empresa llamada City CV, que ayuda a los candidatos a puestos de trabajo con las solicitudes. Ella dice que los sistemas de seguimiento de candidatos (ATS) rechazan hasta el 75% de los CV antes de que un humano los vea. Estos sistemas buscan palabras clave que cumplan con los criterios del empleador. Un consejo es estudiar el lenguaje utilizado en el anuncio de empleo; Si las iniciales PM se utilizan para la gestión de proyectos, asegúrese de que PM aparezca en su CV.

Victoria McLean, ex cazatalentos bancarios y gerente de reclutamiento, fundó una empresa llamada City CV para ayudar a quienes buscan empleo a elaborar sus solicitudes. Dijo que el Sistema de Seguimiento de Solicitantes (ATS) rechaza hasta el 75% de las solicitudes antes de que un humano pueda procesar el currículum. Estos sistemas buscan palabras clave que coincidan con los criterios del empleador. Un consejo rápido es investigar el idioma utilizado en el anuncio de empleo. Si las iniciales PM se utilizan para referirse a la gestión de proyectos, asegúrese de tener PM en su currículum.

Esto significa que un CV genérico puede fracasar ante el primer obstáculo. La señora McLean tenía un cliente que había sido un alto miembro de las fuerzas armadas. Su experiencia apuntaba a posibles puestos de trabajo en formación y educación, adquisiciones o ventas de defensa. La mejor estrategia fue crear tres CV diferentes utilizando diferentes conjuntos de palabras clave. Y los buscadores de empleo también deben asegurarse de que su perfil de LinkedIn y su CV se refuercen mutuamente; La gran mayoría de los reclutadores utilizarán el sitio web para comprobar las cualificaciones de los candidatos, afirma.

Esto significa que es posible que un currículum que no esté orientado ni siquiera supere el primer obstáculo. McClain tenía un cliente que era un oficial militar de alto rango. A juzgar por su currículum, puede tener oportunidades laborales en formación y educación, adquisiciones o venta de armas. La mejor estrategia, afirma, es crear tres currículums diferentes utilizando tres conjuntos diferentes de palabras clave. Los candidatos también deben asegurarse de que su perfil de LinkedIn coincida con su currículum; la gran mayoría de los reclutadores utilizan el sitio para comprobar las calificaciones de los candidatos.

Pasar la etapa ATS puede no ser la única barrera tecnológica para quien busca empleo. Muchas empresas, incluidas Vodafone e Intel, utilizan un servicio de entrevistas por vídeo llamado HireVue. Los candidatos son interrogados mientras un programa de inteligencia artificial (IA) analiza sus expresiones faciales (es aconsejable mantener contacto visual con la cámara) y patrones de lenguaje (el truco es parecer seguro). Las personas que agitan los brazos o se encorvan en el asiento probablemente fracasarán. Sólo si pasan esa prueba los solicitantes conocerán a algunos humanos.

Es posible que ATS no sea el único obstáculo técnico que enfrentan quienes buscan empleo. Muchas empresas, incluidas Vodafone e Intel, han adoptado un servicio de entrevistas en vídeo llamado HireVue. A medida que los candidatos responden preguntas en video, los programas de inteligencia artificial analizan sus expresiones faciales (se recomienda mantener contacto visual con la cámara) y patrones de habla (parecer confiado es clave). Las personas que agitan los brazos o se sientan encorvadas probablemente fracasarán. Sólo después de pasar esta prueba el solicitante de empleo podrá reunirse con algunos entrevistadores.

Se podría esperar que los programas de IA puedan evitar algunos de los sesgos de los métodos de reclutamiento convencionales, especialmente la tendencia de los entrevistadores a favorecer a los candidatos que se parecen al entrevistador. Sin embargo, la discriminación puede manifestarse de maneras inesperadas. Anja Lambrecht y Catherine Tucker, dos economistas, colocaron anuncios que promocionaban empleos en ciencia, tecnología, ingeniería y matemáticas en Facebook. Descubrieron que era menos probable que los anuncios se mostraran a mujeres que a hombres.

Tal vez pensó que un programa de inteligencia artificial podría evitar algunos de los sesgos presentes en los métodos de reclutamiento tradicionales, especialmente la tendencia de los entrevistadores a seleccionar candidatos que sean similares a ellos. Sin embargo, la discriminación puede manifestarse de maneras inesperadas. Dos economistas, Anja Lambrecht y Catherine Tucker, publicaron anuncios en Facebook promocionando oportunidades laborales en ciencia, tecnología, ingeniería y matemáticas. Descubrieron que era más probable que estos anuncios se mostraran a hombres que a mujeres.Esto no se debió a un sesgo consciente por parte del algoritmo de Facebook. Más bien, las mujeres jóvenes son un grupo demográfico más valioso en Facebook (porque controlan una alta proporción del gasto del hogar) y, por lo tanto, los anuncios dirigidos a ellas son más caros. Naturalmente, los algoritmos apuntaron a páginas donde el retorno de la inversión es mayor: para hombres, no para mujeres.

Esto no es el resultado de un sesgo consciente en el algoritmo de Facebook. Por el contrario, las mujeres jóvenes son un grupo más valioso en Facebook (porque controlan una gran parte del gasto del hogar), por lo que los anuncios dirigidos a ellas son más caros. Naturalmente, estos algoritmos se dirigen a páginas con el mayor retorno de la inversión: hombres, no mujeres.

En su libro* sobre inteligencia artificial, Ajay Agrawal, Joshua Gans y Avi Goldfarb, de la Rotman School of Management de Toronto, dicen que las empresas no pueden simplemente descartar tales resultados como un desafortunado efecto secundario de la naturaleza de “caja negra” de los algoritmos. Si descubren que el resultado de un sistema de IA es discriminatorio, deben averiguar por qué y luego ajustar el algoritmo hasta que el efecto desaparezca.

Ajay Agrawal, Joshua Gans y Avi Goldfarb de la Rotman School of Management de la Universidad de Toronto escriben en su coautor sobre inteligencia artificial* que las empresas no pueden simplemente descartar tales resultados como un desafortunado efecto secundario de la naturaleza de “caja negra” de los algoritmos. Si descubren que el resultado de un sistema de IA es discriminatorio, deben descubrir por qué y luego ajustar el algoritmo hasta que el impacto desaparezca.

Han surgido preocupaciones sobre posibles sesgos en los sistemas de IA en una amplia gama de áreas, desde la justicia penal hasta los seguros. También en el ámbito de la contratación, las empresas afrontarán un riesgo legal y de reputación si sus métodos de contratación resultan ser injustos. Pero también deben considerar si los programas hacen algo más que simplificar el proceso. Por ejemplo, ¿los candidatos seleccionados tienen carreras largas y productivas? Después de todo, la rotación de personal es uno de los mayores costos de contratación que enfrentan las empresas.

El potencial de sesgo de los sistemas de IA ha generado preocupación en muchas áreas, desde la justicia penal hasta los seguros. Lo mismo ocurre con la contratación de personal. Si las empresas utilizan métodos de contratación injustos, se enfrentarán a riesgos legales y de reputación. Pero también deben considerar si estos programas pueden hacer algo más que simplificar el proceso de contratación. Por ejemplo, ¿un candidato seleccionado permanecerá en la empresa a largo plazo y de manera productiva? Después de todo, la rotación de personal es uno de los mayores costes de contratación a los que se enfrentan las empresas.

También puede haber una carrera armamentista a medida que los candidatos aprendan a ajustar sus CV para pasar la prueba inicial de IA y los algoritmos se adapten para descartar a más candidatos. Esto crea margen para otro posible sesgo: los candidatos de hogares más acomodados (y de grupos particulares) pueden ser más rápidos en actualizar sus CV. A su vez, esto puede obligar a las empresas a ajustar nuevamente sus algoritmos para evitar la discriminación. Es probable que el precio de la inteligencia artificial sea una vigilancia eterna.

A medida que los candidatos aprendan a modificar sus currículums para pasar la prueba inicial de IA y los algoritmos mejoren para filtrar a más solicitantes, podría desencadenarse una carrera armamentista. Esto crea espacio para otro posible sesgo: los candidatos de familias más ricas (y ciertos grupos) pueden actualizar sus currículums más rápidamente. A su vez, es posible que las empresas deban volver a ajustar sus algoritmos para evitar la discriminación. El precio del uso de la inteligencia artificial parece ser una vigilancia perpetua.

CONSEJOS:

Cómo implementar diferentes tamaños de arco en diferentes esquinas de la vista

Corta las cuatro esquinas derechas de la vista en esquinas redondeadas:

    //设置圆角半径值    
    self.view.layer.cornerRadius  = 10.f;    
    //设置为遮罩,除非view有阴影,否则都要指定为YES的    
    self.view.layer.masksToBounds = YES;
  1. Corta un ángulo recto de la vista en una esquina redondeada:
    //把 view2 的 左下角 和 右下角的直角切成圆角    
    UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(120,10,80,80)];    
    view2.backgroundColor = [UIColor redColor];    
    [self.view addSubview:view2];        
    //设置切哪个直角
    //    UIRectCornerTopLeft     = 1 << 0,  左上角
    //    UIRectCornerTopRight    = 1 << 1,  右上
    //    UIRectCornerBottomLeft  = 1 << 2,  左下角
    //    UIRectCornerBottomRight = 1 << 3,  右下角
    //    UIRectCornerAllCorners  = ~0UL     全部角    
    //得到view的遮罩路径    
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view2.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(10,10)];    
    //创建 layer    
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];    
    maskLayer.frame = view2.bounds;    
//赋值    
maskLayer.path = maskPath.CGPath;

Las esquinas redondeadas establecidas mediante el método anterior tienen el mismo arco para cada esquina redondeada. Entonces, ¿cómo lograr cuatro esquinas con diferentes tamaños de esquinas redondeadas? La clave para lograr las esquinas redondeadas de arriba es la ruta de CAShapeLayer, por lo que solo necesitamos personalizar esta ruta. La implementación es la siguiente:

- (void)setViewRadius:(UIView  *)view{
    CGFloat topLeftRadius = 50;
    CGFloat topRightRadius = 60;
    CGFloat bottomRightRadius = 40;
    CGFloat bottomLeftRadius = 30;
    
    CGFloat minx = CGRectGetMinX(view.bounds);
    CGFloat miny = CGRectGetMinY(view.bounds);
    CGFloat maxx = CGRectGetMaxX(view.bounds);
    CGFloat maxy = CGRectGetMaxY(view.bounds);
    
    UIBezierPath *path = [[UIBezierPath alloc] init];
    [path moveToPoint:CGPointMake(minx + topLeftRadius, miny)];
    
    [path addLineToPoint:CGPointMake(maxx - topRightRadius, miny)];
    [path addArcWithCenter:CGPointMake(maxx - topRightRadius, miny + topRightRadius) radius: topRightRadius startAngle: 3 * M_PI_2 endAngle: 0 clockwise: YES];
    
    [path addLineToPoint:CGPointMake(maxx, maxy - bottomRightRadius)];
    [path addArcWithCenter:CGPointMake(maxx - bottomRightRadius, maxy - bottomRightRadius) radius: bottomRightRadius startAngle: 0 endAngle: M_PI_2 clockwise: YES];
    
    [path addLineToPoint:CGPointMake(minx + bottomLeftRadius, maxy)];
    [path addArcWithCenter:CGPointMake(minx + bottomLeftRadius, maxy - bottomLeftRadius) radius: bottomLeftRadius startAngle: M_PI_2 endAngle:M_PI clockwise: YES];
    
    [path addLineToPoint:CGPointMake(minx, miny + topLeftRadius)];
    [path addArcWithCenter:CGPointMake(minx + topLeftRadius, miny + topLeftRadius) radius: topLeftRadius startAngle: M_PI endAngle:3 * M_PI_2 clockwise: YES];
    
    [path closePath];
    
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.path = path.CGPath;
    view.layer.mask = maskLayer;

Ofrezca otra demostración de UIView para implementar un color degradado.

 UIColor *frameColor = [UIColor colorWithHexString:@"#FFB300"];
            UIColor *toColor = [UIColor colorWithHexString:@"#FF6100"];
            CAGradientLayer *gradientLayer = [CAGradientLayer layer];
            gradientLayer.locations = @[@0.0, @1.0];
            gradientLayer.startPoint = CGPointMake(0, 0);
            gradientLayer.endPoint = CGPointMake(1.0, 0);
            gradientLayer.frame = _bgImageView.bounds;
            gradientLayer.colors = @[(__bridge id)frameColor.CGColor, (__bridge id)toColor.CGColor];
            [_bgImageView.layer insertSublayer:gradientLayer atIndex:0];

Compartir:

Hay una pregunta y respuesta de Zhihu que se está volviendo viral hoy, ~~ ¿La construcción de tecnología de Tencent está actualmente (en 2018) por detrás de empresas del mismo tamaño? ~~,yUna respuesta llamada hardguy se hizo popular, pero la respuesta del autor fue eliminada un día después de su publicación. Sin embargo, hay una copia de seguridad en línea. Si estás interesado, puedes buscarlo.

Permítanme compartir mis pensamientos sobre este tema:

El artículo habla de tecnología deficiente, reservas de talento insuficientes, acuerdos tecnológicos y reglas y regulaciones internas relativamente rígidas dentro de la empresa. La empresa para la que trabajo es realmente así. Muchos de los sistemas de la empresa no favorecen el desarrollo de la tecnología de la empresa. Muchos de los líderes junior de la empresa son personas mayores que llevan más de 5 años en la empresa. Sus habilidades son promedio y han sobrevivido. Algunos de ellos ni siquiera conocen Git y todavía usan SVN. Nadie se atreve a refactorizar el código porque no hay casos de prueba. Si corrige el error, debe asumir la responsabilidad. La actitud del líder es que se puede utilizar.

Se puede decir que el nivel técnico de un equipo depende del liderazgo del mismo. Si el patrón de liderazgo es lo suficientemente grande y la habilidad lo suficientemente fuerte, la creatividad de todo el equipo será fuerte.

Si un líder es complaciente, busca la estabilidad e impide que otros utilicen nuevas tecnologías sin lograr avances, entonces está jodido y debería irse lo antes posible.

En una gran empresa, es difícil para un programador de base cambiar esta situación. Creo que la única manera de cambiar esta situación es desde el liderazgo.

También está la cuestión de las horas extras. De hecho, muchas horas extras en las grandes empresas no se deben a que el trabajo no se pueda completar, sino a que la empresa lo utiliza como estándar para medir la carga de trabajo. De esta forma, pase lo que pase, debe haber suficientes horas extras. Comúnmente conocido como proyecto facial.